{"id":19266576,"url":"https://github.com/koatty/koatty_store","last_synced_at":"2026-03-11T04:32:01.808Z","repository":{"id":57307031,"uuid":"317103657","full_name":"Koatty/koatty_store","owner":"Koatty","description":"Cache store for koatty.","archived":false,"fork":false,"pushed_at":"2025-06-09T04:33:11.000Z","size":1183,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-09T05:26:39.649Z","etag":null,"topics":["components","memory-cache","redis-cache"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Koatty.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-11-30T03:45:20.000Z","updated_at":"2025-06-09T04:33:17.000Z","dependencies_parsed_at":"2025-04-11T18:04:48.032Z","dependency_job_id":"fa22706e-8bb0-4fb1-913f-51838fb0671f","html_url":"https://github.com/Koatty/koatty_store","commit_stats":{"total_commits":36,"total_committers":2,"mean_commits":18.0,"dds":0.02777777777777779,"last_synced_commit":"604d31df38814a530b32605668542821b608cb7d"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/Koatty/koatty_store","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Koatty%2Fkoatty_store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Koatty%2Fkoatty_store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Koatty%2Fkoatty_store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Koatty%2Fkoatty_store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Koatty","download_url":"https://codeload.github.com/Koatty/koatty_store/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Koatty%2Fkoatty_store/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259877007,"owners_count":22925398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["components","memory-cache","redis-cache"],"created_at":"2024-11-09T20:05:52.919Z","updated_at":"2026-03-11T04:32:01.799Z","avatar_url":"https://github.com/Koatty.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# koatty_store\n\n[![Version npm](https://img.shields.io/npm/v/koatty_store.svg?style=flat-square)](https://www.npmjs.com/package/koatty_store)\n[![npm Downloads](https://img.shields.io/npm/dm/koatty_store.svg?style=flat-square)](https://npmjs.org/package/koatty_store)\n\nCache store (memory or redis) for Koatty framework.\n\n## Features\n\n- 🚀 **Dual Storage**: Support both in-memory and Redis storage\n- 💾 **LRU Cache**: Built-in LRU cache with configurable size\n- ⏰ **TTL Support**: Field-level TTL for hash operations\n- 🔒 **Concurrency Safe**: Atomic operations with lock protection\n- 📊 **Rich Data Types**: String, Hash, List, Set, Sorted Set\n- 🔄 **Auto Reconnect**: Redis connection with retry mechanism\n- 🎯 **Type Safe**: Full TypeScript support\n- 📦 **Lightweight**: Minimal dependencies\n\n## Installation\n\n```bash\nnpm install koatty_store\n```\n\n## Quick Start\n\n### Memory Store\n\n```typescript\nimport { CacheStore } from 'koatty_store';\n\n// Create memory store\nconst store = new CacheStore({\n  type: 'memory',\n  keyPrefix: 'myapp:',\n  maxKeys: 1000\n});\n\n// String operations\nawait store.set('user:1', 'John', 60); // Expires in 60 seconds\nconst value = await store.get('user:1');\n\n// Hash operations\nawait store.hset('user:info', 'name', 'John');\nawait store.hset('user:info', 'age', '25');\nconst name = await store.hget('user:info', 'name');\n\n// List operations\nawait store.rpush('queue', 'task1');\nawait store.rpush('queue', 'task2');\nconst task = await store.lpop('queue');\n\n// Close store\nawait store.close();\n```\n\n### Redis Store\n\n```typescript\nimport { CacheStore } from 'koatty_store';\n\n// Create redis store\nconst store = new CacheStore({\n  type: 'redis',\n  host: '127.0.0.1',\n  port: 6379,\n  password: 'your-password',\n  db: 0,\n  keyPrefix: 'myapp:',\n  poolSize: 10\n});\n\n// Use same API as memory store\nawait store.set('key', 'value');\nawait store.close();\n```\n\n## Configuration\n\n### Memory Store Options\n\n```typescript\ninterface MemoryStoreOpt {\n  type: 'memory';\n  keyPrefix?: string;          // Key prefix, default: 'Koatty'\n  db?: number;                 // Database index, default: 0\n  timeout?: number;            // Default TTL in seconds, default: 600\n  maxKeys?: number;            // LRU max keys, default: 1000\n  maxMemory?: number;          // Max memory in bytes\n  evictionPolicy?: 'lru' | 'lfu' | 'random'; // Eviction policy, default: 'lru'\n  ttlCheckInterval?: number;   // TTL check interval in ms, default: 60000\n}\n```\n\n### Redis Store Options\n\n```typescript\ninterface RedisStoreOpt {\n  type: 'redis';\n  host: string;                // Redis host\n  port: number;                // Redis port\n  password?: string;           // Redis password\n  db?: number;                 // Database index, default: 0\n  keyPrefix?: string;          // Key prefix, default: 'Koatty'\n  timeout?: number;            // Default TTL in seconds, default: 600\n  poolSize?: number;           // Connection pool size, default: 10\n  connectTimeout?: number;     // Connection timeout in ms, default: 500\n}\n```\n\n## API Reference\n\n### String Operations\n\n```typescript\n// Set a string value with optional TTL\nawait store.set(key: string, value: string | number, timeout?: number): Promise\u003cstring\u003e\n\n// Get a string value\nawait store.get(key: string): Promise\u003cstring | null\u003e\n\n// Delete a key\nawait store.del(key: string): Promise\u003cnumber\u003e\n\n// Check if key exists\nawait store.exists(key: string): Promise\u003cnumber\u003e\n\n// Get TTL of a key\nawait store.ttl(key: string): Promise\u003cnumber\u003e\n\n// Set TTL for a key\nawait store.expire(key: string, timeout: number): Promise\u003cnumber\u003e\n\n// Increment\nawait store.incr(key: string): Promise\u003cnumber\u003e\nawait store.incrby(key: string, increment: number): Promise\u003cnumber\u003e\n\n// Decrement\nawait store.decr(key: string): Promise\u003cnumber\u003e\nawait store.decrby(key: string, decrement: number): Promise\u003cnumber\u003e\n```\n\n### Hash Operations\n\n```typescript\n// Set hash field with optional TTL (field-level)\nawait store.hset(name: string, key: string, value: string | number, timeout?: number): Promise\u003cnumber\u003e\n\n// Get hash field\nawait store.hget(name: string, key: string): Promise\u003cstring | null\u003e\n\n// Delete hash field\nawait store.hdel(name: string, key: string): Promise\u003cnumber\u003e\n\n// Check if hash field exists\nawait store.hexists(name: string, key: string): Promise\u003cnumber\u003e\n\n// Get all fields and values\nawait store.hgetall(name: string): Promise\u003cany\u003e\n\n// Get all field names\nawait store.hkeys(name: string): Promise\u003cstring[]\u003e\n\n// Get all values\nawait store.hvals(name: string): Promise\u003cany[]\u003e\n\n// Get hash length\nawait store.hlen(name: string): Promise\u003cnumber\u003e\n\n// Increment hash field\nawait store.hincrby(name: string, key: string, increment: number): Promise\u003cnumber\u003e\n```\n\n### List Operations\n\n```typescript\n// Push to right\nawait store.rpush(name: string, value: string | number): Promise\u003cnumber\u003e\n\n// Push to left\nawait store.lpush(name: string, value: string | number): Promise\u003cnumber\u003e\n\n// Pop from left\nawait store.lpop(name: string): Promise\u003cstring | null\u003e\n\n// Pop from right\nawait store.rpop(name: string): Promise\u003cstring | null\u003e\n\n// Get list length\nawait store.llen(name: string): Promise\u003cnumber\u003e\n\n// Get range\nawait store.lrange(name: string, start: number, stop: number): Promise\u003cany[]\u003e\n```\n\n### Set Operations\n\n```typescript\n// Add member with optional TTL\nawait store.sadd(name: string, value: string | number, timeout?: number): Promise\u003cnumber\u003e\n\n// Remove member\nawait store.srem(name: string, key: string): Promise\u003cnumber\u003e\n\n// Get set size\nawait store.scard(name: string): Promise\u003cnumber\u003e\n\n// Check if member exists\nawait store.sismember(name: string, key: string): Promise\u003cnumber\u003e\n\n// Get all members\nawait store.smembers(name: string): Promise\u003cany[]\u003e\n\n// Pop random member\nawait store.spop(name: string): Promise\u003cany\u003e\n\n// Move member between sets\nawait store.smove(source: string, destination: string, member: string): Promise\u003cnumber\u003e\n```\n\n## Advanced Features\n\n### Field-Level TTL for Hash\n\n```typescript\n// Set hash field with TTL (expires in 60 seconds)\nawait store.hset('user:session', 'token', 'abc123', 60);\n\n// Field will be automatically deleted after TTL expires\nsetTimeout(async () =\u003e {\n  const token = await store.hget('user:session', 'token');\n  console.log(token); // null\n}, 61000);\n```\n\n### Singleton Pattern\n\n```typescript\n// Get singleton instance\nconst store1 = CacheStore.getInstance({\n  type: 'memory',\n  keyPrefix: 'app:'\n}, 'cache1');\n\nconst store2 = CacheStore.getInstance({\n  type: 'memory',\n  keyPrefix: 'app:'\n}, 'cache1');\n\nconsole.log(store1 === store2); // true\n\n// Clear specific instance\nawait CacheStore.clearInstance('cache1');\n\n// Clear all instances\nawait CacheStore.clearAllInstances();\n```\n\n### Concurrency Safe Operations\n\nAll atomic operations (incr, decr, incrby, decrby, hincrby) are protected with locks to ensure data consistency in concurrent scenarios.\n\n```typescript\n// Safe concurrent increments\nawait Promise.all([\n  store.incr('counter'),\n  store.incr('counter'),\n  store.incr('counter')\n]);\n\nconst count = await store.get('counter');\nconsole.log(count); // \"3\" - guaranteed consistency\n```\n\n## Best Practices\n\n### 1. Use Key Prefix\n\n```typescript\nconst store = new CacheStore({\n  type: 'memory',\n  keyPrefix: 'myapp:' // Prefix all keys\n});\n```\n\n### 2. Set Appropriate TTL\n\n```typescript\n// Short-lived data\nawait store.set('session:token', token, 3600); // 1 hour\n\n// Long-lived data\nawait store.set('user:profile', profile, 86400); // 24 hours\n```\n\n### 3. Handle Errors Gracefully\n\n```typescript\ntry {\n  await store.set('key', 'value');\n} catch (error) {\n  console.error('Cache operation failed:', error.message);\n  // Fallback to database or other source\n}\n```\n\n### 4. Close Store on Exit\n\n```typescript\nprocess.on('SIGINT', async () =\u003e {\n  await store.close();\n  process.exit(0);\n});\n```\n\n### 5. Use Connection Pool for Redis\n\n```typescript\nconst store = new CacheStore({\n  type: 'redis',\n  host: '127.0.0.1',\n  port: 6379,\n  poolSize: 20 // Adjust based on load\n});\n```\n\n## Testing\n\n```bash\n# Run tests\nnpm test\n\n# Run tests with coverage\nnpm test -- --coverage\n\n# Run specific test\nnpm test -- test/memory.test.ts\n```\n\n## Performance\n\n### Memory Store\n- **Operations**: ~1,000,000 ops/sec\n- **LRU Eviction**: O(1)\n- **TTL Check**: Background task, configurable interval\n\n### Redis Store\n- **Operations**: Depends on Redis server\n- **Connection Pool**: Configurable size\n- **Auto Reconnect**: Exponential backoff strategy\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for release history.\n\n## License\n\nBSD-3-Clause\n\n## Contributing\n\nContributions are welcome! Please read the [contributing guidelines](https://github.com/koatty/koatty_store/blob/master/CONTRIBUTING.md) first.\n\n## Support\n\n- [GitHub Issues](https://github.com/koatty/koatty_store/issues)\n- [Documentation](https://koatty.com)\n\n## Related Projects\n\n- [koatty](https://github.com/koatty/koatty) - The Koatty framework\n- [koatty_lib](https://github.com/koatty/koatty_lib) - Koatty utilities\n- [koatty_logger](https://github.com/koatty/koatty_logger) - Koatty logger\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoatty%2Fkoatty_store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkoatty%2Fkoatty_store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoatty%2Fkoatty_store/lists"}