https://github.com/koatty/koatty_store
Cache store for koatty.
https://github.com/koatty/koatty_store
components memory-cache redis-cache
Last synced: 12 days ago
JSON representation
Cache store for koatty.
- Host: GitHub
- URL: https://github.com/koatty/koatty_store
- Owner: Koatty
- License: bsd-3-clause
- Created: 2020-11-30T03:45:20.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2025-06-09T04:33:11.000Z (10 months ago)
- Last Synced: 2025-06-09T05:26:39.649Z (10 months ago)
- Topics: components, memory-cache, redis-cache
- Language: TypeScript
- Homepage:
- Size: 1.13 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# koatty_store
[](https://www.npmjs.com/package/koatty_store)
[](https://npmjs.org/package/koatty_store)
Cache store (memory or redis) for Koatty framework.
## Features
- 🚀 **Dual Storage**: Support both in-memory and Redis storage
- 💾 **LRU Cache**: Built-in LRU cache with configurable size
- ⏰ **TTL Support**: Field-level TTL for hash operations
- 🔒 **Concurrency Safe**: Atomic operations with lock protection
- 📊 **Rich Data Types**: String, Hash, List, Set, Sorted Set
- 🔄 **Auto Reconnect**: Redis connection with retry mechanism
- 🎯 **Type Safe**: Full TypeScript support
- 📦 **Lightweight**: Minimal dependencies
## Installation
```bash
npm install koatty_store
```
## Quick Start
### Memory Store
```typescript
import { CacheStore } from 'koatty_store';
// Create memory store
const store = new CacheStore({
type: 'memory',
keyPrefix: 'myapp:',
maxKeys: 1000
});
// String operations
await store.set('user:1', 'John', 60); // Expires in 60 seconds
const value = await store.get('user:1');
// Hash operations
await store.hset('user:info', 'name', 'John');
await store.hset('user:info', 'age', '25');
const name = await store.hget('user:info', 'name');
// List operations
await store.rpush('queue', 'task1');
await store.rpush('queue', 'task2');
const task = await store.lpop('queue');
// Close store
await store.close();
```
### Redis Store
```typescript
import { CacheStore } from 'koatty_store';
// Create redis store
const store = new CacheStore({
type: 'redis',
host: '127.0.0.1',
port: 6379,
password: 'your-password',
db: 0,
keyPrefix: 'myapp:',
poolSize: 10
});
// Use same API as memory store
await store.set('key', 'value');
await store.close();
```
## Configuration
### Memory Store Options
```typescript
interface MemoryStoreOpt {
type: 'memory';
keyPrefix?: string; // Key prefix, default: 'Koatty'
db?: number; // Database index, default: 0
timeout?: number; // Default TTL in seconds, default: 600
maxKeys?: number; // LRU max keys, default: 1000
maxMemory?: number; // Max memory in bytes
evictionPolicy?: 'lru' | 'lfu' | 'random'; // Eviction policy, default: 'lru'
ttlCheckInterval?: number; // TTL check interval in ms, default: 60000
}
```
### Redis Store Options
```typescript
interface RedisStoreOpt {
type: 'redis';
host: string; // Redis host
port: number; // Redis port
password?: string; // Redis password
db?: number; // Database index, default: 0
keyPrefix?: string; // Key prefix, default: 'Koatty'
timeout?: number; // Default TTL in seconds, default: 600
poolSize?: number; // Connection pool size, default: 10
connectTimeout?: number; // Connection timeout in ms, default: 500
}
```
## API Reference
### String Operations
```typescript
// Set a string value with optional TTL
await store.set(key: string, value: string | number, timeout?: number): Promise
// Get a string value
await store.get(key: string): Promise
// Delete a key
await store.del(key: string): Promise
// Check if key exists
await store.exists(key: string): Promise
// Get TTL of a key
await store.ttl(key: string): Promise
// Set TTL for a key
await store.expire(key: string, timeout: number): Promise
// Increment
await store.incr(key: string): Promise
await store.incrby(key: string, increment: number): Promise
// Decrement
await store.decr(key: string): Promise
await store.decrby(key: string, decrement: number): Promise
```
### Hash Operations
```typescript
// Set hash field with optional TTL (field-level)
await store.hset(name: string, key: string, value: string | number, timeout?: number): Promise
// Get hash field
await store.hget(name: string, key: string): Promise
// Delete hash field
await store.hdel(name: string, key: string): Promise
// Check if hash field exists
await store.hexists(name: string, key: string): Promise
// Get all fields and values
await store.hgetall(name: string): Promise
// Get all field names
await store.hkeys(name: string): Promise
// Get all values
await store.hvals(name: string): Promise
// Get hash length
await store.hlen(name: string): Promise
// Increment hash field
await store.hincrby(name: string, key: string, increment: number): Promise
```
### List Operations
```typescript
// Push to right
await store.rpush(name: string, value: string | number): Promise
// Push to left
await store.lpush(name: string, value: string | number): Promise
// Pop from left
await store.lpop(name: string): Promise
// Pop from right
await store.rpop(name: string): Promise
// Get list length
await store.llen(name: string): Promise
// Get range
await store.lrange(name: string, start: number, stop: number): Promise
```
### Set Operations
```typescript
// Add member with optional TTL
await store.sadd(name: string, value: string | number, timeout?: number): Promise
// Remove member
await store.srem(name: string, key: string): Promise
// Get set size
await store.scard(name: string): Promise
// Check if member exists
await store.sismember(name: string, key: string): Promise
// Get all members
await store.smembers(name: string): Promise
// Pop random member
await store.spop(name: string): Promise
// Move member between sets
await store.smove(source: string, destination: string, member: string): Promise
```
## Advanced Features
### Field-Level TTL for Hash
```typescript
// Set hash field with TTL (expires in 60 seconds)
await store.hset('user:session', 'token', 'abc123', 60);
// Field will be automatically deleted after TTL expires
setTimeout(async () => {
const token = await store.hget('user:session', 'token');
console.log(token); // null
}, 61000);
```
### Singleton Pattern
```typescript
// Get singleton instance
const store1 = CacheStore.getInstance({
type: 'memory',
keyPrefix: 'app:'
}, 'cache1');
const store2 = CacheStore.getInstance({
type: 'memory',
keyPrefix: 'app:'
}, 'cache1');
console.log(store1 === store2); // true
// Clear specific instance
await CacheStore.clearInstance('cache1');
// Clear all instances
await CacheStore.clearAllInstances();
```
### Concurrency Safe Operations
All atomic operations (incr, decr, incrby, decrby, hincrby) are protected with locks to ensure data consistency in concurrent scenarios.
```typescript
// Safe concurrent increments
await Promise.all([
store.incr('counter'),
store.incr('counter'),
store.incr('counter')
]);
const count = await store.get('counter');
console.log(count); // "3" - guaranteed consistency
```
## Best Practices
### 1. Use Key Prefix
```typescript
const store = new CacheStore({
type: 'memory',
keyPrefix: 'myapp:' // Prefix all keys
});
```
### 2. Set Appropriate TTL
```typescript
// Short-lived data
await store.set('session:token', token, 3600); // 1 hour
// Long-lived data
await store.set('user:profile', profile, 86400); // 24 hours
```
### 3. Handle Errors Gracefully
```typescript
try {
await store.set('key', 'value');
} catch (error) {
console.error('Cache operation failed:', error.message);
// Fallback to database or other source
}
```
### 4. Close Store on Exit
```typescript
process.on('SIGINT', async () => {
await store.close();
process.exit(0);
});
```
### 5. Use Connection Pool for Redis
```typescript
const store = new CacheStore({
type: 'redis',
host: '127.0.0.1',
port: 6379,
poolSize: 20 // Adjust based on load
});
```
## Testing
```bash
# Run tests
npm test
# Run tests with coverage
npm test -- --coverage
# Run specific test
npm test -- test/memory.test.ts
```
## Performance
### Memory Store
- **Operations**: ~1,000,000 ops/sec
- **LRU Eviction**: O(1)
- **TTL Check**: Background task, configurable interval
### Redis Store
- **Operations**: Depends on Redis server
- **Connection Pool**: Configurable size
- **Auto Reconnect**: Exponential backoff strategy
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for release history.
## License
BSD-3-Clause
## Contributing
Contributions are welcome! Please read the [contributing guidelines](https://github.com/koatty/koatty_store/blob/master/CONTRIBUTING.md) first.
## Support
- [GitHub Issues](https://github.com/koatty/koatty_store/issues)
- [Documentation](https://koatty.com)
## Related Projects
- [koatty](https://github.com/koatty/koatty) - The Koatty framework
- [koatty_lib](https://github.com/koatty/koatty_lib) - Koatty utilities
- [koatty_logger](https://github.com/koatty/koatty_logger) - Koatty logger