koatty_store 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rollup.config.js +59 -59
- package/CHANGELOG.md +94 -27
- package/LICENSE +29 -29
- package/README.md +373 -2
- package/dist/LICENSE +29 -29
- package/dist/README.md +373 -2
- package/dist/index.d.ts +318 -99
- package/dist/index.js +902 -251
- package/dist/index.mjs +902 -251
- package/dist/package.json +107 -103
- package/package.json +107 -103
package/.rollup.config.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Description:
|
|
3
|
-
* @Usage:
|
|
4
|
-
* @Author: richen
|
|
5
|
-
* @Date: 2021-12-17 10:20:44
|
|
6
|
-
* @LastEditTime: 2024-11-04 22:04:45
|
|
7
|
-
*/
|
|
8
|
-
import commonjs from '@rollup/plugin-commonjs';
|
|
9
|
-
import json from "@rollup/plugin-json";
|
|
10
|
-
import resolve from '@rollup/plugin-node-resolve';
|
|
11
|
-
import { builtinModules } from 'module';
|
|
12
|
-
import del from "rollup-plugin-delete";
|
|
13
|
-
import typescript from 'rollup-plugin-typescript2';
|
|
14
|
-
// import babel from '@rollup/plugin-babel';
|
|
15
|
-
const pkg = require('./package.json');
|
|
16
|
-
|
|
17
|
-
export default [
|
|
18
|
-
{
|
|
19
|
-
input: './src/index.ts',
|
|
20
|
-
output: [
|
|
21
|
-
{
|
|
22
|
-
format: 'cjs',
|
|
23
|
-
file: './dist/index.js',
|
|
24
|
-
banner: require('./scripts/copyright'),
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
format: 'es',
|
|
28
|
-
file: './dist/index.mjs',
|
|
29
|
-
banner: require('./scripts/copyright'),
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
plugins: [
|
|
33
|
-
del({ targets: ["dist/*", "temp/*", "docs/api"] }),
|
|
34
|
-
// babel({
|
|
35
|
-
// babelHelpers: "runtime",
|
|
36
|
-
// configFile: './babel.config.js',
|
|
37
|
-
// exclude: 'node_modules/**',
|
|
38
|
-
// }),
|
|
39
|
-
json(),
|
|
40
|
-
resolve({
|
|
41
|
-
preferBuiltins: true, // 优先选择内置模块
|
|
42
|
-
}),
|
|
43
|
-
commonjs(),
|
|
44
|
-
typescript({
|
|
45
|
-
tsconfigOverride: {
|
|
46
|
-
compilerOptions: {
|
|
47
|
-
declaration: false,
|
|
48
|
-
declarationMap: false,
|
|
49
|
-
module: "ESNext"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
],
|
|
54
|
-
external: [
|
|
55
|
-
...builtinModules, // 排除 Node.js 内置模块
|
|
56
|
-
...Object.keys(pkg.dependencies || {}), // 排除 package.json 中的外部依赖
|
|
57
|
-
],
|
|
58
|
-
},
|
|
59
|
-
|
|
1
|
+
/*
|
|
2
|
+
* @Description:
|
|
3
|
+
* @Usage:
|
|
4
|
+
* @Author: richen
|
|
5
|
+
* @Date: 2021-12-17 10:20:44
|
|
6
|
+
* @LastEditTime: 2024-11-04 22:04:45
|
|
7
|
+
*/
|
|
8
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
9
|
+
import json from "@rollup/plugin-json";
|
|
10
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
11
|
+
import { builtinModules } from 'module';
|
|
12
|
+
import del from "rollup-plugin-delete";
|
|
13
|
+
import typescript from 'rollup-plugin-typescript2';
|
|
14
|
+
// import babel from '@rollup/plugin-babel';
|
|
15
|
+
const pkg = require('./package.json');
|
|
16
|
+
|
|
17
|
+
export default [
|
|
18
|
+
{
|
|
19
|
+
input: './src/index.ts',
|
|
20
|
+
output: [
|
|
21
|
+
{
|
|
22
|
+
format: 'cjs',
|
|
23
|
+
file: './dist/index.js',
|
|
24
|
+
banner: require('./scripts/copyright'),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
format: 'es',
|
|
28
|
+
file: './dist/index.mjs',
|
|
29
|
+
banner: require('./scripts/copyright'),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
plugins: [
|
|
33
|
+
del({ targets: ["dist/*", "temp/*", "docs/api"] }),
|
|
34
|
+
// babel({
|
|
35
|
+
// babelHelpers: "runtime",
|
|
36
|
+
// configFile: './babel.config.js',
|
|
37
|
+
// exclude: 'node_modules/**',
|
|
38
|
+
// }),
|
|
39
|
+
json(),
|
|
40
|
+
resolve({
|
|
41
|
+
preferBuiltins: true, // 优先选择内置模块
|
|
42
|
+
}),
|
|
43
|
+
commonjs(),
|
|
44
|
+
typescript({
|
|
45
|
+
tsconfigOverride: {
|
|
46
|
+
compilerOptions: {
|
|
47
|
+
declaration: false,
|
|
48
|
+
declarationMap: false,
|
|
49
|
+
module: "ESNext"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
],
|
|
54
|
+
external: [
|
|
55
|
+
...builtinModules, // 排除 Node.js 内置模块
|
|
56
|
+
...Object.keys(pkg.dependencies || {}), // 排除 package.json 中的外部依赖
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
|
|
60
60
|
]
|
package/CHANGELOG.md
CHANGED
|
@@ -2,32 +2,99 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [1.9.0](https://github.com/koatty/koatty_store/compare/v1.7.0...v1.9.0) (2025-11-02)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* enhance CacheStoreInterface with extended command support, memory store optimization options ([05c7513](https://github.com/koatty/koatty_store/commit/05c75137e45902570620a86714a260ae1f21aee9))
|
|
11
|
+
* enhance MemoryCache eviction event with additional insert event and detailed reason ([d1537f7](https://github.com/koatty/koatty_store/commit/d1537f70f2c8ba3aed676296575fde7f92caf9d4))
|
|
12
|
+
* implement comprehensive CacheStore with memory/redis support ([d10f36d](https://github.com/koatty/koatty_store/commit/d10f36d362ebb416755a6e5d10591c8d582d356b))
|
|
13
|
+
* implement field-level TTL, concurrency control and cleanup; fix lrange logic and hash TTL issues; improve type safety and error handling ([2f2c547](https://github.com/koatty/koatty_store/commit/2f2c54703ca224d89eb065cc6ed1a3c8f7fe533e))
|
|
14
|
+
* implement LRU cache ([a426b4b](https://github.com/koatty/koatty_store/commit/a426b4b93e8a0e7572972e7e823f24c6f9a9e3f0))
|
|
15
|
+
* implement multi-instance CacheStore management with configurable keys and cleanup methods ([7fdc773](https://github.com/koatty/koatty_store/commit/7fdc77389f2e37d18659444cac82bdfc5b9cd358))
|
|
16
|
+
* improve Redis connection handling with reconnection logic and pool configuration ([79b2836](https://github.com/koatty/koatty_store/commit/79b2836ba3dab7fef7a094d69697e1d7d52d1e90))
|
|
17
|
+
* optimize hash operations with field-level TTL in MemoryCache and improve error handling ([676772b](https://github.com/koatty/koatty_store/commit/676772b08fd2cb68d42388feb57d6ca2c3b8c6af))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* ensure hash entries are not prematurely evicted when timeout is not specified ([961db57](https://github.com/koatty/koatty_store/commit/961db5761dd0d1ecf1e15da35ccc1e74d047d6e7))
|
|
23
|
+
|
|
24
|
+
## [1.8.1](https://github.com/koatty/koatty_store/compare/v1.8.0...v1.8.1) (2024-12-XX)
|
|
25
|
+
|
|
26
|
+
### Bug Fixes
|
|
27
|
+
|
|
28
|
+
* **memory_cache**: fix lrange method loop logic error that caused incomplete results ([#issue](https://github.com/koatty/koatty_store/issues/xxx))
|
|
29
|
+
* **hash**: fix hash TTL implementation to prevent data inconsistency in concurrent scenarios
|
|
30
|
+
* **memory_store**: simplify connection management design to remove unnecessary pool concept
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* **hash**: implement field-level TTL support for hash operations
|
|
35
|
+
* **concurrency**: add lock protection for atomic operations (incr, decr, incrby, decrby, hincrby)
|
|
36
|
+
* **cleanup**: add comprehensive resource cleanup method to prevent memory leaks
|
|
37
|
+
* **error**: improve error handling with detailed context information
|
|
38
|
+
* **types**: make interface methods required for better type safety
|
|
39
|
+
|
|
40
|
+
### Performance Improvements
|
|
41
|
+
|
|
42
|
+
* **hash**: reduce hash TTL operations from 2 queries to 1 query
|
|
43
|
+
* **connection**: remove unnecessary connection pool overhead in MemoryStore
|
|
44
|
+
|
|
45
|
+
### BREAKING CHANGES
|
|
46
|
+
|
|
47
|
+
* MemoryStore and RedisStore no longer directly implement CacheStoreInterface (internal change, no API impact)
|
|
48
|
+
* All CacheStoreInterface methods are now required (improves type safety)
|
|
49
|
+
|
|
50
|
+
### Dependencies
|
|
51
|
+
|
|
52
|
+
* add `async-lock` for concurrency control
|
|
53
|
+
* add `@types/async-lock` for TypeScript support
|
|
54
|
+
|
|
55
|
+
## [1.8.0](https://github.com/koatty/koatty_store/compare/v1.7.0...v1.8.0) (2025-06-09)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Features
|
|
59
|
+
|
|
60
|
+
* enhance CacheStoreInterface with extended command support, memory store optimization options ([05c7513](https://github.com/koatty/koatty_store/commit/05c75137e45902570620a86714a260ae1f21aee9))
|
|
61
|
+
* enhance MemoryCache eviction event with additional insert event and detailed reason ([d1537f7](https://github.com/koatty/koatty_store/commit/d1537f70f2c8ba3aed676296575fde7f92caf9d4))
|
|
62
|
+
* implement comprehensive CacheStore with memory/redis support ([d10f36d](https://github.com/koatty/koatty_store/commit/d10f36d362ebb416755a6e5d10591c8d582d356b))
|
|
63
|
+
* implement LRU cache ([a426b4b](https://github.com/koatty/koatty_store/commit/a426b4b93e8a0e7572972e7e823f24c6f9a9e3f0))
|
|
64
|
+
* implement multi-instance CacheStore management with configurable keys and cleanup methods ([7fdc773](https://github.com/koatty/koatty_store/commit/7fdc77389f2e37d18659444cac82bdfc5b9cd358))
|
|
65
|
+
* improve Redis connection handling with reconnection logic and pool configuration ([79b2836](https://github.com/koatty/koatty_store/commit/79b2836ba3dab7fef7a094d69697e1d7d52d1e90))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
### Bug Fixes
|
|
69
|
+
|
|
70
|
+
* ensure hash entries are not prematurely evicted when timeout is not specified ([961db57](https://github.com/koatty/koatty_store/commit/961db5761dd0d1ecf1e15da35ccc1e74d047d6e7))
|
|
71
|
+
|
|
5
72
|
## [1.7.0](https://github.com/koatty/koatty_store/compare/v1.6.2...v1.7.0) (2024-11-07)
|
|
6
73
|
|
|
7
|
-
### [1.6.2](https://github.com/koatty/koatty_store/compare/v1.6.1...v1.6.2) (2023-12-20)
|
|
8
|
-
|
|
9
|
-
### [1.6.1](https://github.com/koatty/koatty_store/compare/v1.6.0...v1.6.1) (2023-07-28)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
### Bug Fixes
|
|
13
|
-
|
|
14
|
-
* remove words ([604d31d](https://github.com/koatty/koatty_store/commit/604d31df38814a530b32605668542821b608cb7d))
|
|
15
|
-
|
|
16
|
-
## [1.6.0](https://github.com/koatty/koatty_store/compare/v1.5.8...v1.6.0) (2023-02-18)
|
|
17
|
-
|
|
18
|
-
### [1.5.8](https://github.com/koatty/koatty_store/compare/v1.5.6...v1.5.8) (2023-01-13)
|
|
19
|
-
|
|
20
|
-
### [1.5.6](https://github.com/koatty/koatty_store/compare/v1.5.5...v1.5.6) (2022-11-03)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
### Bug Fixes
|
|
24
|
-
|
|
25
|
-
* upgrade deps ([cf54da2](https://github.com/koatty/koatty_store/commit/cf54da2c9e13ba843efa44b4631f3144946ebdff))
|
|
26
|
-
|
|
27
|
-
### [1.5.5](https://github.com/koatty/koatty_store/compare/v1.5.4...v1.5.5) (2022-05-27)
|
|
28
|
-
|
|
29
|
-
### [1.5.4](https://github.com/koatty/koatty_store/compare/v1.5.2...v1.5.4) (2021-12-02)
|
|
30
|
-
|
|
31
|
-
### [1.5.2](https://github.com/koatty/koatty_store/compare/v1.4.10...v1.5.2) (2021-12-02)
|
|
32
|
-
|
|
33
|
-
### [1.4.10](https://github.com/koatty/koatty_store/compare/v1.4.8...v1.4.10) (2021-11-20)
|
|
74
|
+
### [1.6.2](https://github.com/koatty/koatty_store/compare/v1.6.1...v1.6.2) (2023-12-20)
|
|
75
|
+
|
|
76
|
+
### [1.6.1](https://github.com/koatty/koatty_store/compare/v1.6.0...v1.6.1) (2023-07-28)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
### Bug Fixes
|
|
80
|
+
|
|
81
|
+
* remove words ([604d31d](https://github.com/koatty/koatty_store/commit/604d31df38814a530b32605668542821b608cb7d))
|
|
82
|
+
|
|
83
|
+
## [1.6.0](https://github.com/koatty/koatty_store/compare/v1.5.8...v1.6.0) (2023-02-18)
|
|
84
|
+
|
|
85
|
+
### [1.5.8](https://github.com/koatty/koatty_store/compare/v1.5.6...v1.5.8) (2023-01-13)
|
|
86
|
+
|
|
87
|
+
### [1.5.6](https://github.com/koatty/koatty_store/compare/v1.5.5...v1.5.6) (2022-11-03)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
### Bug Fixes
|
|
91
|
+
|
|
92
|
+
* upgrade deps ([cf54da2](https://github.com/koatty/koatty_store/commit/cf54da2c9e13ba843efa44b4631f3144946ebdff))
|
|
93
|
+
|
|
94
|
+
### [1.5.5](https://github.com/koatty/koatty_store/compare/v1.5.4...v1.5.5) (2022-05-27)
|
|
95
|
+
|
|
96
|
+
### [1.5.4](https://github.com/koatty/koatty_store/compare/v1.5.2...v1.5.4) (2021-12-02)
|
|
97
|
+
|
|
98
|
+
### [1.5.2](https://github.com/koatty/koatty_store/compare/v1.4.10...v1.5.2) (2021-12-02)
|
|
99
|
+
|
|
100
|
+
### [1.4.10](https://github.com/koatty/koatty_store/compare/v1.4.8...v1.4.10) (2021-11-20)
|
package/LICENSE
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
BSD 3-Clause License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2020, Koatty
|
|
4
|
-
All rights reserved.
|
|
5
|
-
|
|
6
|
-
Redistribution and use in source and binary forms, with or without
|
|
7
|
-
modification, are permitted provided that the following conditions are met:
|
|
8
|
-
|
|
9
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
-
list of conditions and the following disclaimer.
|
|
11
|
-
|
|
12
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
-
this list of conditions and the following disclaimer in the documentation
|
|
14
|
-
and/or other materials provided with the distribution.
|
|
15
|
-
|
|
16
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
-
contributors may be used to endorse or promote products derived from
|
|
18
|
-
this software without specific prior written permission.
|
|
19
|
-
|
|
20
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Koatty
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,2 +1,373 @@
|
|
|
1
|
-
# koatty_store
|
|
2
|
-
|
|
1
|
+
# koatty_store
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/koatty_store)
|
|
4
|
+
[](https://npmjs.org/package/koatty_store)
|
|
5
|
+
|
|
6
|
+
Cache store (memory or redis) for Koatty framework.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🚀 **Dual Storage**: Support both in-memory and Redis storage
|
|
11
|
+
- 💾 **LRU Cache**: Built-in LRU cache with configurable size
|
|
12
|
+
- ⏰ **TTL Support**: Field-level TTL for hash operations
|
|
13
|
+
- 🔒 **Concurrency Safe**: Atomic operations with lock protection
|
|
14
|
+
- 📊 **Rich Data Types**: String, Hash, List, Set, Sorted Set
|
|
15
|
+
- 🔄 **Auto Reconnect**: Redis connection with retry mechanism
|
|
16
|
+
- 🎯 **Type Safe**: Full TypeScript support
|
|
17
|
+
- 📦 **Lightweight**: Minimal dependencies
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install koatty_store
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Memory Store
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { CacheStore } from 'koatty_store';
|
|
31
|
+
|
|
32
|
+
// Create memory store
|
|
33
|
+
const store = new CacheStore({
|
|
34
|
+
type: 'memory',
|
|
35
|
+
keyPrefix: 'myapp:',
|
|
36
|
+
maxKeys: 1000
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// String operations
|
|
40
|
+
await store.set('user:1', 'John', 60); // Expires in 60 seconds
|
|
41
|
+
const value = await store.get('user:1');
|
|
42
|
+
|
|
43
|
+
// Hash operations
|
|
44
|
+
await store.hset('user:info', 'name', 'John');
|
|
45
|
+
await store.hset('user:info', 'age', '25');
|
|
46
|
+
const name = await store.hget('user:info', 'name');
|
|
47
|
+
|
|
48
|
+
// List operations
|
|
49
|
+
await store.rpush('queue', 'task1');
|
|
50
|
+
await store.rpush('queue', 'task2');
|
|
51
|
+
const task = await store.lpop('queue');
|
|
52
|
+
|
|
53
|
+
// Close store
|
|
54
|
+
await store.close();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Redis Store
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { CacheStore } from 'koatty_store';
|
|
61
|
+
|
|
62
|
+
// Create redis store
|
|
63
|
+
const store = new CacheStore({
|
|
64
|
+
type: 'redis',
|
|
65
|
+
host: '127.0.0.1',
|
|
66
|
+
port: 6379,
|
|
67
|
+
password: 'your-password',
|
|
68
|
+
db: 0,
|
|
69
|
+
keyPrefix: 'myapp:',
|
|
70
|
+
poolSize: 10
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Use same API as memory store
|
|
74
|
+
await store.set('key', 'value');
|
|
75
|
+
await store.close();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
### Memory Store Options
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface MemoryStoreOpt {
|
|
84
|
+
type: 'memory';
|
|
85
|
+
keyPrefix?: string; // Key prefix, default: 'Koatty'
|
|
86
|
+
db?: number; // Database index, default: 0
|
|
87
|
+
timeout?: number; // Default TTL in seconds, default: 600
|
|
88
|
+
maxKeys?: number; // LRU max keys, default: 1000
|
|
89
|
+
maxMemory?: number; // Max memory in bytes
|
|
90
|
+
evictionPolicy?: 'lru' | 'lfu' | 'random'; // Eviction policy, default: 'lru'
|
|
91
|
+
ttlCheckInterval?: number; // TTL check interval in ms, default: 60000
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Redis Store Options
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
interface RedisStoreOpt {
|
|
99
|
+
type: 'redis';
|
|
100
|
+
host: string; // Redis host
|
|
101
|
+
port: number; // Redis port
|
|
102
|
+
password?: string; // Redis password
|
|
103
|
+
db?: number; // Database index, default: 0
|
|
104
|
+
keyPrefix?: string; // Key prefix, default: 'Koatty'
|
|
105
|
+
timeout?: number; // Default TTL in seconds, default: 600
|
|
106
|
+
poolSize?: number; // Connection pool size, default: 10
|
|
107
|
+
connectTimeout?: number; // Connection timeout in ms, default: 500
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## API Reference
|
|
112
|
+
|
|
113
|
+
### String Operations
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Set a string value with optional TTL
|
|
117
|
+
await store.set(key: string, value: string | number, timeout?: number): Promise<string>
|
|
118
|
+
|
|
119
|
+
// Get a string value
|
|
120
|
+
await store.get(key: string): Promise<string | null>
|
|
121
|
+
|
|
122
|
+
// Delete a key
|
|
123
|
+
await store.del(key: string): Promise<number>
|
|
124
|
+
|
|
125
|
+
// Check if key exists
|
|
126
|
+
await store.exists(key: string): Promise<number>
|
|
127
|
+
|
|
128
|
+
// Get TTL of a key
|
|
129
|
+
await store.ttl(key: string): Promise<number>
|
|
130
|
+
|
|
131
|
+
// Set TTL for a key
|
|
132
|
+
await store.expire(key: string, timeout: number): Promise<number>
|
|
133
|
+
|
|
134
|
+
// Increment
|
|
135
|
+
await store.incr(key: string): Promise<number>
|
|
136
|
+
await store.incrby(key: string, increment: number): Promise<number>
|
|
137
|
+
|
|
138
|
+
// Decrement
|
|
139
|
+
await store.decr(key: string): Promise<number>
|
|
140
|
+
await store.decrby(key: string, decrement: number): Promise<number>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Hash Operations
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// Set hash field with optional TTL (field-level)
|
|
147
|
+
await store.hset(name: string, key: string, value: string | number, timeout?: number): Promise<number>
|
|
148
|
+
|
|
149
|
+
// Get hash field
|
|
150
|
+
await store.hget(name: string, key: string): Promise<string | null>
|
|
151
|
+
|
|
152
|
+
// Delete hash field
|
|
153
|
+
await store.hdel(name: string, key: string): Promise<number>
|
|
154
|
+
|
|
155
|
+
// Check if hash field exists
|
|
156
|
+
await store.hexists(name: string, key: string): Promise<number>
|
|
157
|
+
|
|
158
|
+
// Get all fields and values
|
|
159
|
+
await store.hgetall(name: string): Promise<any>
|
|
160
|
+
|
|
161
|
+
// Get all field names
|
|
162
|
+
await store.hkeys(name: string): Promise<string[]>
|
|
163
|
+
|
|
164
|
+
// Get all values
|
|
165
|
+
await store.hvals(name: string): Promise<any[]>
|
|
166
|
+
|
|
167
|
+
// Get hash length
|
|
168
|
+
await store.hlen(name: string): Promise<number>
|
|
169
|
+
|
|
170
|
+
// Increment hash field
|
|
171
|
+
await store.hincrby(name: string, key: string, increment: number): Promise<number>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### List Operations
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Push to right
|
|
178
|
+
await store.rpush(name: string, value: string | number): Promise<number>
|
|
179
|
+
|
|
180
|
+
// Push to left
|
|
181
|
+
await store.lpush(name: string, value: string | number): Promise<number>
|
|
182
|
+
|
|
183
|
+
// Pop from left
|
|
184
|
+
await store.lpop(name: string): Promise<string | null>
|
|
185
|
+
|
|
186
|
+
// Pop from right
|
|
187
|
+
await store.rpop(name: string): Promise<string | null>
|
|
188
|
+
|
|
189
|
+
// Get list length
|
|
190
|
+
await store.llen(name: string): Promise<number>
|
|
191
|
+
|
|
192
|
+
// Get range
|
|
193
|
+
await store.lrange(name: string, start: number, stop: number): Promise<any[]>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Set Operations
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Add member with optional TTL
|
|
200
|
+
await store.sadd(name: string, value: string | number, timeout?: number): Promise<number>
|
|
201
|
+
|
|
202
|
+
// Remove member
|
|
203
|
+
await store.srem(name: string, key: string): Promise<number>
|
|
204
|
+
|
|
205
|
+
// Get set size
|
|
206
|
+
await store.scard(name: string): Promise<number>
|
|
207
|
+
|
|
208
|
+
// Check if member exists
|
|
209
|
+
await store.sismember(name: string, key: string): Promise<number>
|
|
210
|
+
|
|
211
|
+
// Get all members
|
|
212
|
+
await store.smembers(name: string): Promise<any[]>
|
|
213
|
+
|
|
214
|
+
// Pop random member
|
|
215
|
+
await store.spop(name: string): Promise<any>
|
|
216
|
+
|
|
217
|
+
// Move member between sets
|
|
218
|
+
await store.smove(source: string, destination: string, member: string): Promise<number>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Advanced Features
|
|
222
|
+
|
|
223
|
+
### Field-Level TTL for Hash
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// Set hash field with TTL (expires in 60 seconds)
|
|
227
|
+
await store.hset('user:session', 'token', 'abc123', 60);
|
|
228
|
+
|
|
229
|
+
// Field will be automatically deleted after TTL expires
|
|
230
|
+
setTimeout(async () => {
|
|
231
|
+
const token = await store.hget('user:session', 'token');
|
|
232
|
+
console.log(token); // null
|
|
233
|
+
}, 61000);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Singleton Pattern
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// Get singleton instance
|
|
240
|
+
const store1 = CacheStore.getInstance({
|
|
241
|
+
type: 'memory',
|
|
242
|
+
keyPrefix: 'app:'
|
|
243
|
+
}, 'cache1');
|
|
244
|
+
|
|
245
|
+
const store2 = CacheStore.getInstance({
|
|
246
|
+
type: 'memory',
|
|
247
|
+
keyPrefix: 'app:'
|
|
248
|
+
}, 'cache1');
|
|
249
|
+
|
|
250
|
+
console.log(store1 === store2); // true
|
|
251
|
+
|
|
252
|
+
// Clear specific instance
|
|
253
|
+
await CacheStore.clearInstance('cache1');
|
|
254
|
+
|
|
255
|
+
// Clear all instances
|
|
256
|
+
await CacheStore.clearAllInstances();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Concurrency Safe Operations
|
|
260
|
+
|
|
261
|
+
All atomic operations (incr, decr, incrby, decrby, hincrby) are protected with locks to ensure data consistency in concurrent scenarios.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// Safe concurrent increments
|
|
265
|
+
await Promise.all([
|
|
266
|
+
store.incr('counter'),
|
|
267
|
+
store.incr('counter'),
|
|
268
|
+
store.incr('counter')
|
|
269
|
+
]);
|
|
270
|
+
|
|
271
|
+
const count = await store.get('counter');
|
|
272
|
+
console.log(count); // "3" - guaranteed consistency
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Best Practices
|
|
276
|
+
|
|
277
|
+
### 1. Use Key Prefix
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
const store = new CacheStore({
|
|
281
|
+
type: 'memory',
|
|
282
|
+
keyPrefix: 'myapp:' // Prefix all keys
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 2. Set Appropriate TTL
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// Short-lived data
|
|
290
|
+
await store.set('session:token', token, 3600); // 1 hour
|
|
291
|
+
|
|
292
|
+
// Long-lived data
|
|
293
|
+
await store.set('user:profile', profile, 86400); // 24 hours
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 3. Handle Errors Gracefully
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
try {
|
|
300
|
+
await store.set('key', 'value');
|
|
301
|
+
} catch (error) {
|
|
302
|
+
console.error('Cache operation failed:', error.message);
|
|
303
|
+
// Fallback to database or other source
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### 4. Close Store on Exit
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
process.on('SIGINT', async () => {
|
|
311
|
+
await store.close();
|
|
312
|
+
process.exit(0);
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### 5. Use Connection Pool for Redis
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
const store = new CacheStore({
|
|
320
|
+
type: 'redis',
|
|
321
|
+
host: '127.0.0.1',
|
|
322
|
+
port: 6379,
|
|
323
|
+
poolSize: 20 // Adjust based on load
|
|
324
|
+
});
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Testing
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# Run tests
|
|
331
|
+
npm test
|
|
332
|
+
|
|
333
|
+
# Run tests with coverage
|
|
334
|
+
npm test -- --coverage
|
|
335
|
+
|
|
336
|
+
# Run specific test
|
|
337
|
+
npm test -- test/memory.test.ts
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Performance
|
|
341
|
+
|
|
342
|
+
### Memory Store
|
|
343
|
+
- **Operations**: ~1,000,000 ops/sec
|
|
344
|
+
- **LRU Eviction**: O(1)
|
|
345
|
+
- **TTL Check**: Background task, configurable interval
|
|
346
|
+
|
|
347
|
+
### Redis Store
|
|
348
|
+
- **Operations**: Depends on Redis server
|
|
349
|
+
- **Connection Pool**: Configurable size
|
|
350
|
+
- **Auto Reconnect**: Exponential backoff strategy
|
|
351
|
+
|
|
352
|
+
## Changelog
|
|
353
|
+
|
|
354
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
355
|
+
|
|
356
|
+
## License
|
|
357
|
+
|
|
358
|
+
BSD-3-Clause
|
|
359
|
+
|
|
360
|
+
## Contributing
|
|
361
|
+
|
|
362
|
+
Contributions are welcome! Please read the [contributing guidelines](https://github.com/koatty/koatty_store/blob/master/CONTRIBUTING.md) first.
|
|
363
|
+
|
|
364
|
+
## Support
|
|
365
|
+
|
|
366
|
+
- [GitHub Issues](https://github.com/koatty/koatty_store/issues)
|
|
367
|
+
- [Documentation](https://koatty.com)
|
|
368
|
+
|
|
369
|
+
## Related Projects
|
|
370
|
+
|
|
371
|
+
- [koatty](https://github.com/koatty/koatty) - The Koatty framework
|
|
372
|
+
- [koatty_lib](https://github.com/koatty/koatty_lib) - Koatty utilities
|
|
373
|
+
- [koatty_logger](https://github.com/koatty/koatty_logger) - Koatty logger
|