@abtnode/db-cache 1.16.45-beta-20250609-111118-0d252ebe → 1.16.45-beta-20250612-231219-481217be

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/README.md CHANGED
@@ -2,17 +2,21 @@
2
2
 
3
3
  Use Redis or Sqlite3 LRC cache, multithread safe
4
4
 
5
- 约定: DB Cache 不能作为数据的单一来源, 我们要假定 Cache 的数据随时可能被释放来进行业务开发.
6
- 不限制 cache 个数: Redis 我们约定直接在 redis 配置好最大内存和达到内存上限时自动移除旧的; Sqlite 由于使用的是硬盘, 也没有必要限制上限.
5
+ **Convention:** DB Cache must not be the sole source of truth. We must assume that cache data can be released at any time during development.
7
6
 
8
- 约定 Redis 启动配置:
7
+ **No limit on the number of caches:**
9
8
 
10
- - 确保 redis 仅在内网
11
- - 不做持久化
12
- - 最大只用 512MB 内存
13
- - 内存满时对所有键做 LRU (最近最久未使用) 淘汰
9
+ For Redis, we configure it with a max memory limit and enable automatic LRU (Least Recently Used) eviction when full.
10
+ For SQLite, since it's disk-based, there's no need to limit the size.
14
11
 
15
- ```
12
+ ## Redis Startup Configuration
13
+
14
+ - Redis bound to the internal network only
15
+ - No persistence
16
+ - Max memory: 512MB
17
+ - Eviction policy: allkeys-lru (LRU for all keys)
18
+
19
+ ```bash
16
20
  docker run -d \
17
21
  --name db-cache-redis \
18
22
  -p 127.0.0.1:40409:6379 \
@@ -26,7 +30,7 @@ docker run -d \
26
30
 
27
31
  ## Usage
28
32
 
29
- ```shell
33
+ ```bash
30
34
  yarn add @abtnode/db-cache
31
35
  ```
32
36
 
@@ -35,7 +39,7 @@ Then:
35
39
  ```javascript
36
40
  const { DBCache } = require('@abtnode/db-cache');
37
41
 
38
- // 当第一次使用时, 才会去读取配置
42
+ // Configuration will only be read on first use
39
43
  const dbCache = new DBCache(() => ({
40
44
  prefix: 'the prefix key',
41
45
  ttl: 60 * 1000,
@@ -50,7 +54,7 @@ await dbCache.delete('key');
50
54
  await dbCache.has('key');
51
55
  ```
52
56
 
53
- ## hash set/get 的使用
57
+ ## Group set/get usage
54
58
 
55
59
  ```javascript
56
60
  const cache = new DBCache(() => ({
@@ -63,41 +67,61 @@ const cache = new DBCache(() => ({
63
67
  await cache.groupSet('group-key', 'sub-key', { a: 'b' });
64
68
  const data = await cache.groupGet('group-key', 'sub-key');
65
69
  await cache.groupDel('group-key', 'sub-key');
66
- await cache.del('group-key'); // delete group all key
70
+ await cache.del('group-key'); // delete all keys under the group
67
71
  ```
68
72
 
69
- ## 锁的使用
73
+ ## Auto Cache
74
+
75
+ `autoCache` or `autoCacheGroup`:
76
+
77
+ If the value is cached, return it; otherwise, compute and cache it
78
+
79
+ Errors during computation won't be cached
70
80
 
71
81
  ```javascript
72
- const lock = new DBCache(() => ({
82
+ const cache = new DBCache(() => ({
73
83
  prefix: 'the prefix key',
74
84
  ttl: 5 * 1000,
75
85
  sqlitePath: 'test.db',
76
86
  redisURL: process.env.REDIS_URL,
77
87
  }));
78
- await lock.acquire('key name');
79
- // do something
80
- await lock.releaseLock('key name');
81
88
 
82
- // or wait ttl, auto release lock
89
+ await cache.autoCache('key', async () => {
90
+ return 'want to cache data';
91
+ });
92
+
93
+ await cache.autoCacheGroup('group-key', 'sub-key', async () => {
94
+ return 'want to cache data';
95
+ });
83
96
  ```
84
97
 
85
- ## SQLite 性能
98
+ ## Lock usage
86
99
 
87
- 默认设置压测性能很低,
100
+ ```javascript
101
+ const lock = new DBCache(() => ({
102
+ prefix: 'the prefix key',
103
+ ttl: 5 * 1000,
104
+ sqlitePath: 'test.db',
105
+ redisURL: process.env.REDIS_URL,
106
+ }));
88
107
 
89
- 多线程测试安全, 但是并发非常慢, 放弃所有安全性 (不适合)
108
+ await lock.acquire('key name');
109
+ // do something or wait for TTL to auto-release the lock
110
+ await lock.releaseLock('key name');
111
+ ```
90
112
 
91
- 使用 WAL (最后使用的方案)
113
+ ## SQLite Performance
92
114
 
93
- ```
94
- PRAGMA journal_mode = WAL; -- 写前日志并行读写
95
- PRAGMA synchronous = OFF; -- 放弃每次 fsync,追求速度
96
- PRAGMA busy_timeout = 10000; -- 锁冲突时最多等 10
97
- PRAGMA wal_autocheckpoint = 2000; -- 2000 次写后自动做一次 checkpoint
115
+ **SQLite auto set WAL mode**
116
+
117
+ ```sql
118
+ PRAGMA journal_mode = WAL; -- Enable Write-Ahead Logging for parallel reads/writes
119
+ PRAGMA synchronous = OFF; -- Skip fsync for performance
120
+ PRAGMA busy_timeout = 10000; -- Wait up to 10 seconds on lock conflict
121
+ PRAGMA wal_autocheckpoint = 2000; -- Auto-checkpoint after every 2000 writes
98
122
  ```
99
123
 
100
- 压测结果:
124
+ ### Benchmark Results
101
125
 
102
126
  ```
103
127
  === SQLite Backend Benchmark ===
@@ -109,27 +133,28 @@ SET 50000 ops in 0.14s -> 370370 ops/sec
109
133
  GET 50000 ops in 0.14s -> 349650 ops/sec
110
134
  ```
111
135
 
112
- 磁盘或硬盘开销:
136
+ ### Disk or Memory Usage
113
137
 
114
- ```
138
+ Example with 100,000 entries. Sample data:
115
139
 
116
- 10w 条数据, 数据样本:
140
+ ```json
117
141
  {
118
- idx: i,
119
- v: `value-${i}`,
120
- other: `other-${i}`,
121
- other2: `other2-${i}`,
122
- other3: `other3-${i}`,
123
- other4: `other4-${i}`,
124
- other5: `other5-${i}`,
125
- other6: `other6-${i}`,
126
- other7: `other7-${i}`,
127
- other8: `other8-${i}`,
128
- other9: `other9-${i}`,
129
- other10: `other10-${i}`,
130
- }
131
-
142
+ idx: i,
143
+ v: `value-${i}`,
144
+ other: `other-${i}`,
145
+ other2: `other2-${i}`,
146
+ other3: `other3-${i}`,
147
+ other4: `other4-${i}`,
148
+ other5: `other5-${i}`,
149
+ other6: `other6-${i}`,
150
+ other7: `other7-${i}`,
151
+ other8: `other8-${i}`,
152
+ other9: `other9-${i}`,
153
+ other10: `other10-${i}`,
154
+ }
155
+ ```
132
156
 
157
+ ```
133
158
  === Redis Memory Info ===
134
159
  # Memory
135
160
  used_memory_rss_human:57.41M
@@ -137,17 +162,18 @@ used_memory_rss_human:57.41M
137
162
  SQLite file size: 31.63 MB
138
163
  ```
139
164
 
140
- 并发测试是安全的, 取决于 busy_timeout 的时长和并发数
165
+ Concurrency is safe and depends on `busy_timeout` and the level of concurrency.
141
166
 
142
- 结论, Redis 大概会是 SQLite 20-40 倍性能, 但是 SQLite 不会成为业务的 QPS 瓶颈. SQLite 可以在 RPS 要求不是这么高的情况下, 用硬盘换内存, 还是挺划算的.
167
+ **Conclusion:** Redis is roughly 20–40x faster than SQLite. However, SQLite will not be the QPS bottleneck in most business use cases. It's a cost-effective choice for trading disk space for memory in scenarios with moderate RPS demands.
143
168
 
144
- #### group 实现差异
169
+ ---
145
170
 
146
- group redis 使用 hash set 数据结构, 性能差异较小
171
+ ### Group Implementation Differences
147
172
 
148
- sqlite group 相当于使用两个 key 进行查询, 性能也很不错
173
+ - Redis: groups are implemented via hash sets — performance is very good.
174
+ - SQLite: implemented with dual-key lookups — still performs well.
149
175
 
150
- 下面是 group set/get 的性能:
176
+ **Group set/get performance:**
151
177
 
152
178
  ```
153
179
  === SQLite Backend Benchmark ===
@@ -159,12 +185,15 @@ SET 50000 ops in 0.22s -> 230415 ops/sec
159
185
  GET 50000 ops in 0.08s -> 649351 ops/sec
160
186
  ```
161
187
 
162
- #### CI 测试 redis
188
+ ---
163
189
 
164
- TEST_REDIS_URL 环境变量就测试 Redis 模式, 没有就测试 SQLite 模式
190
+ ### CI Redis Testing
165
191
 
166
- 例子:
192
+ If the `TEST_REDIS_URL` environment variable is set, tests will run in Redis mode.
193
+ If not, tests will fall back to SQLite mode.
167
194
 
168
- ```
195
+ Example:
196
+
197
+ ```bash
169
198
  TEST_REDIS_URL="redis://:the_password@127.0.0.1:6379"
170
199
  ```
package/dist/index.cjs CHANGED
@@ -822,10 +822,14 @@ const isJestTest = () => {
822
822
  return process.env.NODE_ENV === "test" || process.env.BABEL_ENV === "test" || typeof jest !== "undefined";
823
823
  };
824
824
  const getAbtNodeRedisAndSQLiteUrl = () => {
825
- return {
825
+ const params = {
826
826
  redisUrl: process.env.ABT_NODE_CACHE_REDIS_URL,
827
827
  sqlitePath: isJestTest() ? "test.db" : process.env.ABT_NODE_CACHE_SQLITE_PATH
828
828
  };
829
+ if (process.env.ABT_NODE_NO_CACHE === "true") {
830
+ params.ttl = 1;
831
+ }
832
+ return params;
829
833
  };
830
834
 
831
835
  exports.DBCache = LockDBCache;
package/dist/index.mjs CHANGED
@@ -802,10 +802,14 @@ const isJestTest = () => {
802
802
  return process.env.NODE_ENV === "test" || process.env.BABEL_ENV === "test" || typeof jest !== "undefined";
803
803
  };
804
804
  const getAbtNodeRedisAndSQLiteUrl = () => {
805
- return {
805
+ const params = {
806
806
  redisUrl: process.env.ABT_NODE_CACHE_REDIS_URL,
807
807
  sqlitePath: isJestTest() ? "test.db" : process.env.ABT_NODE_CACHE_SQLITE_PATH
808
808
  };
809
+ if (process.env.ABT_NODE_NO_CACHE === "true") {
810
+ params.ttl = 1;
811
+ }
812
+ return params;
809
813
  };
810
814
 
811
815
  export { LockDBCache as DBCache, getAbtNodeRedisAndSQLiteUrl };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abtnode/db-cache",
3
- "version": "1.16.45-beta-20250609-111118-0d252ebe",
3
+ "version": "1.16.45-beta-20250612-231219-481217be",
4
4
  "description": "Db cache use redis or sqlite as backend",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -44,5 +44,5 @@
44
44
  "typescript": "^5.6.3",
45
45
  "unbuild": "^2.0.0"
46
46
  },
47
- "gitHead": "3ea8ca1f5debfddd15b172c9dd9f4d4eaf22db0e"
47
+ "gitHead": "01a3fb21f16a515e2565d12797baeda5fdf585b0"
48
48
  }