@yunzai-ng/core 0.1.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/LICENSE +661 -0
- package/README.md +51 -0
- package/dist/adapter/accounts.d.ts +174 -0
- package/dist/adapter/accounts.d.ts.map +1 -0
- package/dist/adapter/accounts.js +653 -0
- package/dist/adapter/accounts.js.map +1 -0
- package/dist/adapter/bots.d.ts +142 -0
- package/dist/adapter/bots.d.ts.map +1 -0
- package/dist/adapter/bots.js +454 -0
- package/dist/adapter/bots.js.map +1 -0
- package/dist/adapter/host.d.ts +114 -0
- package/dist/adapter/host.d.ts.map +1 -0
- package/dist/adapter/host.js +90 -0
- package/dist/adapter/host.js.map +1 -0
- package/dist/adapter/login.d.ts +174 -0
- package/dist/adapter/login.d.ts.map +1 -0
- package/dist/adapter/login.js +345 -0
- package/dist/adapter/login.js.map +1 -0
- package/dist/adapter/registry.d.ts +102 -0
- package/dist/adapter/registry.d.ts.map +1 -0
- package/dist/adapter/registry.js +150 -0
- package/dist/adapter/registry.js.map +1 -0
- package/dist/config/core-config.d.ts +151 -0
- package/dist/config/core-config.d.ts.map +1 -0
- package/dist/config/core-config.js +338 -0
- package/dist/config/core-config.js.map +1 -0
- package/dist/config/schema.d.ts +449 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +871 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/store.d.ts +184 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +428 -0
- package/dist/config/store.js.map +1 -0
- package/dist/config/yaml.d.ts +23 -0
- package/dist/config/yaml.d.ts.map +1 -0
- package/dist/config/yaml.js +108 -0
- package/dist/config/yaml.js.map +1 -0
- package/dist/http/client.d.ts +82 -0
- package/dist/http/client.d.ts.map +1 -0
- package/dist/http/client.js +658 -0
- package/dist/http/client.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/app.d.ts +244 -0
- package/dist/kernel/app.d.ts.map +1 -0
- package/dist/kernel/app.js +654 -0
- package/dist/kernel/app.js.map +1 -0
- package/dist/kernel/kv-sink.d.ts +34 -0
- package/dist/kernel/kv-sink.d.ts.map +1 -0
- package/dist/kernel/kv-sink.js +25 -0
- package/dist/kernel/kv-sink.js.map +1 -0
- package/dist/kernel/policy.d.ts +77 -0
- package/dist/kernel/policy.d.ts.map +1 -0
- package/dist/kernel/policy.js +99 -0
- package/dist/kernel/policy.js.map +1 -0
- package/dist/kernel/runtime.d.ts +117 -0
- package/dist/kernel/runtime.d.ts.map +1 -0
- package/dist/kernel/runtime.js +197 -0
- package/dist/kernel/runtime.js.map +1 -0
- package/dist/kernel/sql-sink.d.ts +36 -0
- package/dist/kernel/sql-sink.d.ts.map +1 -0
- package/dist/kernel/sql-sink.js +114 -0
- package/dist/kernel/sql-sink.js.map +1 -0
- package/dist/logger/format.d.ts +67 -0
- package/dist/logger/format.d.ts.map +1 -0
- package/dist/logger/format.js +218 -0
- package/dist/logger/format.js.map +1 -0
- package/dist/logger/index.d.ts +97 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +363 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/rotate.d.ts +47 -0
- package/dist/logger/rotate.d.ts.map +1 -0
- package/dist/logger/rotate.js +242 -0
- package/dist/logger/rotate.js.map +1 -0
- package/dist/message/segment.d.ts +255 -0
- package/dist/message/segment.d.ts.map +1 -0
- package/dist/message/segment.js +510 -0
- package/dist/message/segment.js.map +1 -0
- package/dist/message/split.d.ts +34 -0
- package/dist/message/split.d.ts.map +1 -0
- package/dist/message/split.js +79 -0
- package/dist/message/split.js.map +1 -0
- package/dist/message/target.d.ts +29 -0
- package/dist/message/target.d.ts.map +1 -0
- package/dist/message/target.js +34 -0
- package/dist/message/target.js.map +1 -0
- package/dist/pipeline/cooldown.d.ts +84 -0
- package/dist/pipeline/cooldown.d.ts.map +1 -0
- package/dist/pipeline/cooldown.js +94 -0
- package/dist/pipeline/cooldown.js.map +1 -0
- package/dist/pipeline/dispatch.d.ts +98 -0
- package/dist/pipeline/dispatch.d.ts.map +1 -0
- package/dist/pipeline/dispatch.js +323 -0
- package/dist/pipeline/dispatch.js.map +1 -0
- package/dist/pipeline/event.d.ts +130 -0
- package/dist/pipeline/event.d.ts.map +1 -0
- package/dist/pipeline/event.js +538 -0
- package/dist/pipeline/event.js.map +1 -0
- package/dist/pipeline/middleware.d.ts +63 -0
- package/dist/pipeline/middleware.d.ts.map +1 -0
- package/dist/pipeline/middleware.js +174 -0
- package/dist/pipeline/middleware.js.map +1 -0
- package/dist/pipeline/prompt.d.ts +80 -0
- package/dist/pipeline/prompt.d.ts.map +1 -0
- package/dist/pipeline/prompt.js +155 -0
- package/dist/pipeline/prompt.js.map +1 -0
- package/dist/pipeline/router.d.ts +98 -0
- package/dist/pipeline/router.d.ts.map +1 -0
- package/dist/pipeline/router.js +489 -0
- package/dist/pipeline/router.js.map +1 -0
- package/dist/platform/detect.d.ts +24 -0
- package/dist/platform/detect.d.ts.map +1 -0
- package/dist/platform/detect.js +178 -0
- package/dist/platform/detect.js.map +1 -0
- package/dist/platform/paths.d.ts +38 -0
- package/dist/platform/paths.d.ts.map +1 -0
- package/dist/platform/paths.js +129 -0
- package/dist/platform/paths.js.map +1 -0
- package/dist/platform/system.d.ts +71 -0
- package/dist/platform/system.d.ts.map +1 -0
- package/dist/platform/system.js +242 -0
- package/dist/platform/system.js.map +1 -0
- package/dist/plugin/context.d.ts +92 -0
- package/dist/plugin/context.d.ts.map +1 -0
- package/dist/plugin/context.js +573 -0
- package/dist/plugin/context.js.map +1 -0
- package/dist/plugin/define.d.ts +92 -0
- package/dist/plugin/define.d.ts.map +1 -0
- package/dist/plugin/define.js +82 -0
- package/dist/plugin/define.js.map +1 -0
- package/dist/plugin/discover.d.ts +106 -0
- package/dist/plugin/discover.d.ts.map +1 -0
- package/dist/plugin/discover.js +254 -0
- package/dist/plugin/discover.js.map +1 -0
- package/dist/plugin/events.d.ts +109 -0
- package/dist/plugin/events.d.ts.map +1 -0
- package/dist/plugin/events.js +209 -0
- package/dist/plugin/events.js.map +1 -0
- package/dist/plugin/hooks.d.ts +266 -0
- package/dist/plugin/hooks.d.ts.map +1 -0
- package/dist/plugin/hooks.js +84 -0
- package/dist/plugin/hooks.js.map +1 -0
- package/dist/plugin/host.d.ts +160 -0
- package/dist/plugin/host.d.ts.map +1 -0
- package/dist/plugin/host.js +546 -0
- package/dist/plugin/host.js.map +1 -0
- package/dist/plugin/market.d.ts +264 -0
- package/dist/plugin/market.d.ts.map +1 -0
- package/dist/plugin/market.js +700 -0
- package/dist/plugin/market.js.map +1 -0
- package/dist/plugin/services.d.ts +116 -0
- package/dist/plugin/services.d.ts.map +1 -0
- package/dist/plugin/services.js +213 -0
- package/dist/plugin/services.js.map +1 -0
- package/dist/plugin/tar.d.ts +65 -0
- package/dist/plugin/tar.d.ts.map +1 -0
- package/dist/plugin/tar.js +277 -0
- package/dist/plugin/tar.js.map +1 -0
- package/dist/render/registry.d.ts +127 -0
- package/dist/render/registry.d.ts.map +1 -0
- package/dist/render/registry.js +306 -0
- package/dist/render/registry.js.map +1 -0
- package/dist/scheduler/index.d.ts +67 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +279 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/server/api.d.ts +179 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +602 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/auth.d.ts +83 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +178 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/browse.d.ts +60 -0
- package/dist/server/browse.d.ts.map +1 -0
- package/dist/server/browse.js +187 -0
- package/dist/server/browse.js.map +1 -0
- package/dist/server/files.d.ts +27 -0
- package/dist/server/files.d.ts.map +1 -0
- package/dist/server/files.js +76 -0
- package/dist/server/files.js.map +1 -0
- package/dist/server/index.d.ts +189 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1123 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/table.d.ts +105 -0
- package/dist/server/table.d.ts.map +1 -0
- package/dist/server/table.js +289 -0
- package/dist/server/table.js.map +1 -0
- package/dist/store/index.d.ts +50 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +120 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/json.d.ts +73 -0
- package/dist/store/json.d.ts.map +1 -0
- package/dist/store/json.js +174 -0
- package/dist/store/json.js.map +1 -0
- package/dist/store/kv.d.ts +126 -0
- package/dist/store/kv.d.ts.map +1 -0
- package/dist/store/kv.js +232 -0
- package/dist/store/kv.js.map +1 -0
- package/dist/store/level.d.ts +103 -0
- package/dist/store/level.d.ts.map +1 -0
- package/dist/store/level.js +119 -0
- package/dist/store/level.js.map +1 -0
- package/dist/store/memory.d.ts +61 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +94 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/store/sql.d.ts +142 -0
- package/dist/store/sql.d.ts.map +1 -0
- package/dist/store/sql.js +246 -0
- package/dist/store/sql.js.map +1 -0
- package/dist/testing/fake.d.ts +109 -0
- package/dist/testing/fake.d.ts.map +1 -0
- package/dist/testing/fake.js +196 -0
- package/dist/testing/fake.js.map +1 -0
- package/dist/testing/index.d.ts +16 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +16 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-adapter.d.ts +205 -0
- package/dist/testing/mock-adapter.d.ts.map +1 -0
- package/dist/testing/mock-adapter.js +309 -0
- package/dist/testing/mock-adapter.js.map +1 -0
- package/dist/util/deep.d.ts +108 -0
- package/dist/util/deep.d.ts.map +1 -0
- package/dist/util/deep.js +275 -0
- package/dist/util/deep.js.map +1 -0
- package/dist/util/defer.d.ts +107 -0
- package/dist/util/defer.d.ts.map +1 -0
- package/dist/util/defer.js +163 -0
- package/dist/util/defer.js.map +1 -0
- package/dist/util/dispose.d.ts +88 -0
- package/dist/util/dispose.d.ts.map +1 -0
- package/dist/util/dispose.js +143 -0
- package/dist/util/dispose.js.map +1 -0
- package/dist/util/duration.d.ts +28 -0
- package/dist/util/duration.d.ts.map +1 -0
- package/dist/util/duration.js +77 -0
- package/dist/util/duration.js.map +1 -0
- package/dist/util/fs.d.ts +110 -0
- package/dist/util/fs.d.ts.map +1 -0
- package/dist/util/fs.js +269 -0
- package/dist/util/fs.js.map +1 -0
- package/dist/util/id.d.ts +49 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +87 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/lru.d.ts +74 -0
- package/dist/util/lru.d.ts.map +1 -0
- package/dist/util/lru.js +156 -0
- package/dist/util/lru.js.map +1 -0
- package/dist/util/queue.d.ts +64 -0
- package/dist/util/queue.d.ts.map +1 -0
- package/dist/util/queue.js +147 -0
- package/dist/util/queue.js.map +1 -0
- package/dist/util/text.d.ts +86 -0
- package/dist/util/text.d.ts.map +1 -0
- package/dist/util/text.js +182 -0
- package/dist/util/text.js.map +1 -0
- package/package.json +44 -0
- package/src/adapter/accounts.ts +758 -0
- package/src/adapter/bots.ts +582 -0
- package/src/adapter/host.ts +224 -0
- package/src/adapter/login.ts +481 -0
- package/src/adapter/registry.ts +202 -0
- package/src/config/core-config.test.ts +60 -0
- package/src/config/core-config.ts +401 -0
- package/src/config/schema.test.ts +179 -0
- package/src/config/schema.ts +1036 -0
- package/src/config/store.test.ts +245 -0
- package/src/config/store.ts +506 -0
- package/src/config/yaml.ts +119 -0
- package/src/http/client.test.ts +568 -0
- package/src/http/client.ts +777 -0
- package/src/index.ts +106 -0
- package/src/kernel/app.test.ts +267 -0
- package/src/kernel/app.ts +843 -0
- package/src/kernel/kv-sink.ts +58 -0
- package/src/kernel/policy.ts +120 -0
- package/src/kernel/runtime.test.ts +542 -0
- package/src/kernel/runtime.ts +307 -0
- package/src/kernel/sql-sink.ts +154 -0
- package/src/logger/format.ts +259 -0
- package/src/logger/index.ts +427 -0
- package/src/logger/rotate.ts +265 -0
- package/src/message/segment.test.ts +335 -0
- package/src/message/segment.ts +569 -0
- package/src/message/split.ts +97 -0
- package/src/message/target.ts +48 -0
- package/src/pipeline/cooldown.ts +136 -0
- package/src/pipeline/dispatch.ts +419 -0
- package/src/pipeline/event.ts +735 -0
- package/src/pipeline/middleware.test.ts +426 -0
- package/src/pipeline/middleware.ts +199 -0
- package/src/pipeline/prompt.ts +212 -0
- package/src/pipeline/router.test.ts +432 -0
- package/src/pipeline/router.ts +575 -0
- package/src/platform/detect.ts +178 -0
- package/src/platform/paths.ts +147 -0
- package/src/platform/system.test.ts +102 -0
- package/src/platform/system.ts +289 -0
- package/src/plugin/context.test.ts +459 -0
- package/src/plugin/context.ts +757 -0
- package/src/plugin/define.test.ts +120 -0
- package/src/plugin/define.ts +142 -0
- package/src/plugin/discover.test.ts +253 -0
- package/src/plugin/discover.ts +353 -0
- package/src/plugin/events.test.ts +162 -0
- package/src/plugin/events.ts +266 -0
- package/src/plugin/hooks.ts +373 -0
- package/src/plugin/host.test.ts +696 -0
- package/src/plugin/host.ts +738 -0
- package/src/plugin/market.test.ts +781 -0
- package/src/plugin/market.ts +870 -0
- package/src/plugin/services.test.ts +135 -0
- package/src/plugin/services.ts +261 -0
- package/src/plugin/tar.test.ts +158 -0
- package/src/plugin/tar.ts +309 -0
- package/src/render/registry.test.ts +127 -0
- package/src/render/registry.ts +439 -0
- package/src/scheduler/index.ts +357 -0
- package/src/server/api.test.ts +802 -0
- package/src/server/api.ts +869 -0
- package/src/server/auth.ts +201 -0
- package/src/server/browse.test.ts +193 -0
- package/src/server/browse.ts +240 -0
- package/src/server/files.ts +97 -0
- package/src/server/index.test.ts +566 -0
- package/src/server/index.ts +1386 -0
- package/src/server/table.ts +351 -0
- package/src/store/index.ts +156 -0
- package/src/store/json.ts +198 -0
- package/src/store/kv.test.ts +307 -0
- package/src/store/kv.ts +256 -0
- package/src/store/level.ts +167 -0
- package/src/store/memory.ts +109 -0
- package/src/store/sql.test.ts +204 -0
- package/src/store/sql.ts +324 -0
- package/src/testing/fake.ts +297 -0
- package/src/testing/index.ts +15 -0
- package/src/testing/mock-adapter.ts +588 -0
- package/src/util/deep.ts +272 -0
- package/src/util/defer.ts +211 -0
- package/src/util/dispose.ts +169 -0
- package/src/util/duration.ts +82 -0
- package/src/util/fs.ts +279 -0
- package/src/util/id.ts +94 -0
- package/src/util/lru.ts +185 -0
- package/src/util/queue.ts +167 -0
- package/src/util/text.ts +189 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块职责:JSON 文件 KV 驱动(纯 JS 兜底,Termux/无编译环境用)
|
|
3
|
+
* 依赖方向:依赖 util/{fs,deep}、类型包
|
|
4
|
+
* 生命周期:`open()` 载入全量数据,`close()` 落盘;进程存续期间数据常驻内存
|
|
5
|
+
* 注意事项:**这是兜底方案,不是主力**。全量数据常驻内存 + 每次写盘重写整个文件,
|
|
6
|
+
* 数据量大了必然吃内存与 IO;只在原生模块装不上(Android/Termux 常见)
|
|
7
|
+
* 时启用,`level` 驱动才是默认。
|
|
8
|
+
*
|
|
9
|
+
* 写盘做了两件事防丢数据:一是合并窗口内的多次写只落一次盘,
|
|
10
|
+
* 二是走 `atomicWrite`(同目录临时文件 + rename),断电不会留下半个文件。
|
|
11
|
+
* 进程退出前必须 `close()`,否则最后一个窗口内的写入会丢。
|
|
12
|
+
*/
|
|
13
|
+
import type { KvBatchOp, KvDriver, StoredEnvelope } from "@yunzai-ng/types";
|
|
14
|
+
/** JSON 文件 KV 驱动 */
|
|
15
|
+
export declare class JsonKvDriver implements KvDriver {
|
|
16
|
+
#private;
|
|
17
|
+
/** 驱动 id */
|
|
18
|
+
readonly id = "json";
|
|
19
|
+
/**
|
|
20
|
+
* @param file 数据文件绝对路径
|
|
21
|
+
*/
|
|
22
|
+
constructor(file: string);
|
|
23
|
+
/** 键数量 */
|
|
24
|
+
get size(): number;
|
|
25
|
+
/**
|
|
26
|
+
* 载入数据
|
|
27
|
+
*
|
|
28
|
+
* 文件损坏时不抛错也不删除:改名为 `.corrupt-<时间戳>` 留证,然后从空库启动。
|
|
29
|
+
* 存储坏了让机器人起不来,比丢一点缓存严重得多。
|
|
30
|
+
*/
|
|
31
|
+
open(): Promise<void>;
|
|
32
|
+
/** 落盘并停止后续写入 */
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* 读取
|
|
36
|
+
* @param key 完整键
|
|
37
|
+
* @returns 值信封副本
|
|
38
|
+
*/
|
|
39
|
+
get(key: string): Promise<StoredEnvelope | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* 写入
|
|
42
|
+
* @param key 完整键
|
|
43
|
+
* @param value 值信封
|
|
44
|
+
*/
|
|
45
|
+
set(key: string, value: StoredEnvelope): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* 删除
|
|
48
|
+
* @param key 完整键
|
|
49
|
+
*/
|
|
50
|
+
del(key: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* 批量操作(只触发一次落盘)
|
|
53
|
+
* @param ops 操作列表
|
|
54
|
+
*/
|
|
55
|
+
batch(ops: KvBatchOp[]): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* 按前缀扫描
|
|
58
|
+
* @param prefix 键前缀
|
|
59
|
+
* @returns 键值对迭代器
|
|
60
|
+
*/
|
|
61
|
+
scan(prefix: string): AsyncIterableIterator<readonly [string, StoredEnvelope]>;
|
|
62
|
+
/**
|
|
63
|
+
* 原生原子自增(同步读改写,单线程下天然原子)
|
|
64
|
+
* @param key 完整键
|
|
65
|
+
* @param by 增量
|
|
66
|
+
* @param expireAt 首次创建时的过期时间点
|
|
67
|
+
* @returns 自增后的值
|
|
68
|
+
*/
|
|
69
|
+
incr(key: string, by: number, expireAt?: number): Promise<number>;
|
|
70
|
+
/** 立即落盘(`close()` 与测试用) */
|
|
71
|
+
flush(): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/store/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAoB3E,oBAAoB;AACpB,qBAAa,YAAa,YAAW,QAAQ;;IAC3C,YAAY;IACZ,QAAQ,CAAC,EAAE,UAAS;IAepB;;OAEG;gBACS,IAAI,EAAE,MAAM;IAIxB,UAAU;IACV,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,gBAAgB;IACV,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAK3D;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC;;;OAGG;IACG,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5C;;;;OAIG;IACI,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IASrF;;;;;;OAMG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvE,2BAA2B;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAuB7B"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { atomicWrite, ensureDir, readText } from "../util/fs.js";
|
|
2
|
+
import { deepClone } from "../util/deep.js";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { isExpired } from "./kv.js";
|
|
5
|
+
/** 落盘合并窗口(毫秒) */
|
|
6
|
+
const FLUSH_DELAY = 300;
|
|
7
|
+
/** 文件格式版本,将来变更结构时用于迁移判断 */
|
|
8
|
+
const FORMAT = 1;
|
|
9
|
+
/** JSON 文件 KV 驱动 */
|
|
10
|
+
export class JsonKvDriver {
|
|
11
|
+
/** 驱动 id */
|
|
12
|
+
id = "json";
|
|
13
|
+
/** 文件绝对路径 */
|
|
14
|
+
#file;
|
|
15
|
+
/** 数据表 */
|
|
16
|
+
#map = new Map();
|
|
17
|
+
/** 落盘定时器 */
|
|
18
|
+
#timer;
|
|
19
|
+
/** 是否有未落盘的改动 */
|
|
20
|
+
#dirty = false;
|
|
21
|
+
/** 正在进行的落盘,用于串行化避免两次写互相覆盖 */
|
|
22
|
+
#writing = Promise.resolve();
|
|
23
|
+
/** 是否已关闭 */
|
|
24
|
+
#closed = false;
|
|
25
|
+
/**
|
|
26
|
+
* @param file 数据文件绝对路径
|
|
27
|
+
*/
|
|
28
|
+
constructor(file) {
|
|
29
|
+
this.#file = file;
|
|
30
|
+
}
|
|
31
|
+
/** 键数量 */
|
|
32
|
+
get size() {
|
|
33
|
+
return this.#map.size;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 载入数据
|
|
37
|
+
*
|
|
38
|
+
* 文件损坏时不抛错也不删除:改名为 `.corrupt-<时间戳>` 留证,然后从空库启动。
|
|
39
|
+
* 存储坏了让机器人起不来,比丢一点缓存严重得多。
|
|
40
|
+
*/
|
|
41
|
+
async open() {
|
|
42
|
+
this.#closed = false;
|
|
43
|
+
await ensureDir(dirname(this.#file));
|
|
44
|
+
const text = await readText(this.#file);
|
|
45
|
+
if (text === undefined || text.trim() === "")
|
|
46
|
+
return;
|
|
47
|
+
try {
|
|
48
|
+
const parsed = JSON.parse(text);
|
|
49
|
+
const data = parsed.format === FORMAT ? parsed.data : undefined;
|
|
50
|
+
if (!data || typeof data !== "object")
|
|
51
|
+
throw new Error("结构不符");
|
|
52
|
+
this.#map = new Map(Object.entries(data));
|
|
53
|
+
// 载入时清掉过期键,避免它们一直占内存直到被访问
|
|
54
|
+
for (const [key, env] of [...this.#map])
|
|
55
|
+
if (isExpired(env))
|
|
56
|
+
this.#map.delete(key);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const backup = `${this.#file}.corrupt-${Date.now()}`;
|
|
60
|
+
await atomicWrite(backup, text).catch(() => undefined);
|
|
61
|
+
throw new Error(`KV 数据文件解析失败,已备份到 ${backup}:${err instanceof Error ? err.message : String(err)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** 落盘并停止后续写入 */
|
|
65
|
+
async close() {
|
|
66
|
+
this.#closed = true;
|
|
67
|
+
if (this.#timer) {
|
|
68
|
+
clearTimeout(this.#timer);
|
|
69
|
+
this.#timer = undefined;
|
|
70
|
+
}
|
|
71
|
+
await this.flush();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 读取
|
|
75
|
+
* @param key 完整键
|
|
76
|
+
* @returns 值信封副本
|
|
77
|
+
*/
|
|
78
|
+
async get(key) {
|
|
79
|
+
const env = this.#map.get(key);
|
|
80
|
+
return env === undefined ? undefined : deepClone(env);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 写入
|
|
84
|
+
* @param key 完整键
|
|
85
|
+
* @param value 值信封
|
|
86
|
+
*/
|
|
87
|
+
async set(key, value) {
|
|
88
|
+
this.#map.set(key, deepClone(value));
|
|
89
|
+
this.#schedule();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 删除
|
|
93
|
+
* @param key 完整键
|
|
94
|
+
*/
|
|
95
|
+
async del(key) {
|
|
96
|
+
if (this.#map.delete(key))
|
|
97
|
+
this.#schedule();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 批量操作(只触发一次落盘)
|
|
101
|
+
* @param ops 操作列表
|
|
102
|
+
*/
|
|
103
|
+
async batch(ops) {
|
|
104
|
+
let changed = false;
|
|
105
|
+
for (const op of ops) {
|
|
106
|
+
if (op.op === "set") {
|
|
107
|
+
this.#map.set(op.key, deepClone(op.value));
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
else if (this.#map.delete(op.key))
|
|
111
|
+
changed = true;
|
|
112
|
+
}
|
|
113
|
+
if (changed)
|
|
114
|
+
this.#schedule();
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 按前缀扫描
|
|
118
|
+
* @param prefix 键前缀
|
|
119
|
+
* @returns 键值对迭代器
|
|
120
|
+
*/
|
|
121
|
+
async *scan(prefix) {
|
|
122
|
+
for (const key of [...this.#map.keys()]) {
|
|
123
|
+
if (!key.startsWith(prefix))
|
|
124
|
+
continue;
|
|
125
|
+
const env = this.#map.get(key);
|
|
126
|
+
if (env === undefined)
|
|
127
|
+
continue;
|
|
128
|
+
yield [key, deepClone(env)];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 原生原子自增(同步读改写,单线程下天然原子)
|
|
133
|
+
* @param key 完整键
|
|
134
|
+
* @param by 增量
|
|
135
|
+
* @param expireAt 首次创建时的过期时间点
|
|
136
|
+
* @returns 自增后的值
|
|
137
|
+
*/
|
|
138
|
+
async incr(key, by, expireAt) {
|
|
139
|
+
const env = this.#map.get(key);
|
|
140
|
+
const alive = env !== undefined && !isExpired(env);
|
|
141
|
+
const current = alive && typeof env.v === "number" ? env.v : 0;
|
|
142
|
+
const next = current + by;
|
|
143
|
+
const keep = alive ? env.e : expireAt;
|
|
144
|
+
this.#map.set(key, keep === undefined ? { v: next } : { v: next, e: keep });
|
|
145
|
+
this.#schedule();
|
|
146
|
+
return next;
|
|
147
|
+
}
|
|
148
|
+
/** 立即落盘(`close()` 与测试用) */
|
|
149
|
+
async flush() {
|
|
150
|
+
if (!this.#dirty)
|
|
151
|
+
return await this.#writing;
|
|
152
|
+
this.#dirty = false;
|
|
153
|
+
const snapshot = { format: FORMAT, data: Object.fromEntries(this.#map) };
|
|
154
|
+
// 串在上一次写之后:两次并发的 atomicWrite 会竞争同一个目标文件
|
|
155
|
+
this.#writing = this.#writing.then(async () => {
|
|
156
|
+
await atomicWrite(this.#file, JSON.stringify(snapshot));
|
|
157
|
+
});
|
|
158
|
+
await this.#writing;
|
|
159
|
+
}
|
|
160
|
+
/** 安排一次延迟落盘 */
|
|
161
|
+
#schedule() {
|
|
162
|
+
this.#dirty = true;
|
|
163
|
+
if (this.#closed || this.#timer)
|
|
164
|
+
return;
|
|
165
|
+
this.#timer = setTimeout(() => {
|
|
166
|
+
this.#timer = undefined;
|
|
167
|
+
void this.flush().catch(() => undefined);
|
|
168
|
+
}, FLUSH_DELAY);
|
|
169
|
+
// unref:等待落盘不该拖住进程退出,退出路径上有 close() 兜底
|
|
170
|
+
if (typeof this.#timer.unref === "function")
|
|
171
|
+
this.#timer.unref();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/store/json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块职责:驱动之上的命名空间化 KV 视图(前缀隔离、TTL、原子自增、前缀遍历)
|
|
3
|
+
* 依赖方向:依赖 util/{duration,queue}、类型包;不认识任何具体驱动
|
|
4
|
+
* 生命周期:与驱动同寿;`Kv` 自身无需回收
|
|
5
|
+
* 注意事项:三条规则 ——
|
|
6
|
+
*
|
|
7
|
+
* 1) **过期为读时判定**,不用定时器扫描 —— 那会在低内存设备上白耗 CPU。读到过期键
|
|
8
|
+
* 即视为不存在并一并删除,遍历时同样机会式清理。
|
|
9
|
+
* 2) **`incr` 在驱动没有原生原子操作时退化为"按键串行的读改写"。** LevelDB 没有 INCR,
|
|
10
|
+
* 直接 `get` + `set` 会让同一秒内的并发消息相互覆盖、计数偏小。`KeyedQueue` 把同一个键
|
|
11
|
+
* 的操作排队,进程内语义正确;跨进程原子性不予承诺(单进程架构无此需要)。
|
|
12
|
+
* 3) **每个插件的键自带 `plugin:<name>:` 前缀**,插件之间不可能访问到对方的键 ——
|
|
13
|
+
* 隔离由前缀保证,不靠命名约定。
|
|
14
|
+
*/
|
|
15
|
+
import type { DurationLike, KvDriver, KvNamespace, KvSetOptions, StoredEnvelope } from "@yunzai-ng/types";
|
|
16
|
+
import { KeyedQueue } from "../util/queue.js";
|
|
17
|
+
/**
|
|
18
|
+
* 命名空间化的 KV 视图
|
|
19
|
+
*
|
|
20
|
+
* 由 `openKv()` 创建根视图,插件通过 `ctx.kv` 拿到 `plugin:<name>:` 子视图。
|
|
21
|
+
*/
|
|
22
|
+
export declare class Kv implements KvNamespace {
|
|
23
|
+
#private;
|
|
24
|
+
/** 本命名空间的键前缀 */
|
|
25
|
+
readonly prefix: string;
|
|
26
|
+
/**
|
|
27
|
+
* @param driver 底层驱动
|
|
28
|
+
* @param prefix 键前缀(含结尾分隔符,根视图为空串)
|
|
29
|
+
* @param queue 自增串行队列;派生子视图时必须沿用父级的队列,
|
|
30
|
+
* 否则同一个键在父子视图里会落到两条队列上,串行保证失效
|
|
31
|
+
*/
|
|
32
|
+
constructor(driver: KvDriver, prefix?: string, queue?: KeyedQueue);
|
|
33
|
+
/**
|
|
34
|
+
* 读取
|
|
35
|
+
* @param key 命名空间内的键
|
|
36
|
+
* @returns 值;不存在或已过期时 undefined
|
|
37
|
+
*/
|
|
38
|
+
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* 读取,不存在时返回默认值
|
|
41
|
+
* @param key 命名空间内的键
|
|
42
|
+
* @param fallback 默认值
|
|
43
|
+
* @returns 值或默认值
|
|
44
|
+
*/
|
|
45
|
+
getOr<T>(key: string, fallback: T): Promise<T>;
|
|
46
|
+
/**
|
|
47
|
+
* 写入
|
|
48
|
+
* @param key 命名空间内的键
|
|
49
|
+
* @param value 值,必须可 JSON 序列化
|
|
50
|
+
* @param opts 写入选项
|
|
51
|
+
*/
|
|
52
|
+
set<T = unknown>(key: string, value: T, opts?: KvSetOptions): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* 删除
|
|
55
|
+
* @param key 命名空间内的键
|
|
56
|
+
*/
|
|
57
|
+
del(key: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* 判断是否存在且未过期
|
|
60
|
+
* @param key 命名空间内的键
|
|
61
|
+
* @returns 是否存在
|
|
62
|
+
*/
|
|
63
|
+
has(key: string): Promise<boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* 原子自增
|
|
66
|
+
*
|
|
67
|
+
* 驱动提供原生 `incr` 就直接用;否则按键串行地读改写。
|
|
68
|
+
* @param key 命名空间内的键
|
|
69
|
+
* @param by 增量,默认 1
|
|
70
|
+
* @param opts 写入选项;`ttl` 只在键首次创建时生效(与 Redis 的 INCR 语义一致:
|
|
71
|
+
* 自增不会刷新过期时间,否则热点计数器永不过期)
|
|
72
|
+
* @returns 自增后的值
|
|
73
|
+
*/
|
|
74
|
+
incr(key: string, by?: number, opts?: KvSetOptions): Promise<number>;
|
|
75
|
+
/**
|
|
76
|
+
* 读取剩余存活毫秒数
|
|
77
|
+
* @param key 命名空间内的键
|
|
78
|
+
* @returns 剩余毫秒;永不过期返回 Infinity;不存在或已过期返回 -1
|
|
79
|
+
*/
|
|
80
|
+
ttl(key: string): Promise<number>;
|
|
81
|
+
/**
|
|
82
|
+
* 遍历键(不含命名空间前缀)
|
|
83
|
+
* @param prefix 命名空间内的额外前缀
|
|
84
|
+
* @returns 键的异步迭代器
|
|
85
|
+
*/
|
|
86
|
+
keys(prefix?: string): AsyncIterableIterator<string>;
|
|
87
|
+
/**
|
|
88
|
+
* 遍历键值
|
|
89
|
+
* @param prefix 命名空间内的额外前缀
|
|
90
|
+
* @returns 键值对的异步迭代器
|
|
91
|
+
*/
|
|
92
|
+
entries<T = unknown>(prefix?: string): AsyncIterableIterator<readonly [string, T]>;
|
|
93
|
+
/**
|
|
94
|
+
* 清空(可按前缀)
|
|
95
|
+
* @param prefix 命名空间内的额外前缀,省略则清空整个命名空间
|
|
96
|
+
* @returns 删除的键数量
|
|
97
|
+
*/
|
|
98
|
+
clear(prefix?: string): Promise<number>;
|
|
99
|
+
/**
|
|
100
|
+
* 派生子命名空间
|
|
101
|
+
* @param name 子命名空间名
|
|
102
|
+
* @returns 新的 KV 视图,与父级共享驱动与自增队列
|
|
103
|
+
* @throws 当名字为空或含分隔符时(否则两个不同的子空间可能拼出同一个前缀)
|
|
104
|
+
*/
|
|
105
|
+
sub(name: string): KvNamespace;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 判断信封是否已过期
|
|
109
|
+
* @param env 值信封
|
|
110
|
+
* @returns 是否过期
|
|
111
|
+
*/
|
|
112
|
+
export declare function isExpired(env: StoredEnvelope): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* 计算过期时间点
|
|
115
|
+
* @param ttl 存活时长
|
|
116
|
+
* @returns 毫秒时间戳;不过期时 undefined
|
|
117
|
+
*/
|
|
118
|
+
export declare function expiryOf(ttl: DurationLike | undefined): number | undefined;
|
|
119
|
+
/**
|
|
120
|
+
* 组装值信封
|
|
121
|
+
* @param value 值
|
|
122
|
+
* @param ttl 存活时长
|
|
123
|
+
* @returns 值信封
|
|
124
|
+
*/
|
|
125
|
+
export declare function envelope(value: unknown, ttl?: DurationLike): StoredEnvelope;
|
|
126
|
+
//# sourceMappingURL=kv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../src/store/kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEzG,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAQ7C;;;;GAIG;AACH,qBAAa,EAAG,YAAW,WAAW;;IACpC,gBAAgB;IAChB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IAOvB;;;;;OAKG;gBACS,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAK,EAAE,KAAK,aAAmB;IAMnE;;;;OAIG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAY3D;;;;;OAKG;IACG,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAKpD;;;;;OAKG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjF;;;OAGG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxC;;;;;;;;;OASG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAI,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBrE;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOvC;;;;OAIG;IACI,IAAI,CAAC,MAAM,SAAK,GAAG,qBAAqB,CAAC,MAAM,CAAC;IAIvD;;;;OAIG;IACI,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,SAAK,GAAG,qBAAqB,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAkBrF;;;;OAIG;IACG,KAAK,CAAC,MAAM,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzC;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;CA2B/B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI1E;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,cAAc,CAG3E"}
|
package/dist/store/kv.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { parseDuration } from "../util/duration.js";
|
|
2
|
+
import { KeyedQueue } from "../util/queue.js";
|
|
3
|
+
/** 命名空间分隔符 */
|
|
4
|
+
const SEP = ":";
|
|
5
|
+
/** 单次遍历中最多清理多少个过期键(有界,避免遍历大库时删除列表耗尽内存) */
|
|
6
|
+
const SWEEP_LIMIT = 256;
|
|
7
|
+
/**
|
|
8
|
+
* 命名空间化的 KV 视图
|
|
9
|
+
*
|
|
10
|
+
* 由 `openKv()` 创建根视图,插件通过 `ctx.kv` 拿到 `plugin:<name>:` 子视图。
|
|
11
|
+
*/
|
|
12
|
+
export class Kv {
|
|
13
|
+
/** 本命名空间的键前缀 */
|
|
14
|
+
prefix;
|
|
15
|
+
/** 底层驱动 */
|
|
16
|
+
#driver;
|
|
17
|
+
/** 自增串行队列,与同一驱动的所有视图共享 */
|
|
18
|
+
#queue;
|
|
19
|
+
/**
|
|
20
|
+
* @param driver 底层驱动
|
|
21
|
+
* @param prefix 键前缀(含结尾分隔符,根视图为空串)
|
|
22
|
+
* @param queue 自增串行队列;派生子视图时必须沿用父级的队列,
|
|
23
|
+
* 否则同一个键在父子视图里会落到两条队列上,串行保证失效
|
|
24
|
+
*/
|
|
25
|
+
constructor(driver, prefix = "", queue = new KeyedQueue()) {
|
|
26
|
+
this.#driver = driver;
|
|
27
|
+
this.prefix = prefix;
|
|
28
|
+
this.#queue = queue;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 读取
|
|
32
|
+
* @param key 命名空间内的键
|
|
33
|
+
* @returns 值;不存在或已过期时 undefined
|
|
34
|
+
*/
|
|
35
|
+
async get(key) {
|
|
36
|
+
const full = this.#full(key);
|
|
37
|
+
const env = await this.#driver.get(full);
|
|
38
|
+
if (env === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
if (isExpired(env)) {
|
|
41
|
+
// 读到过期键即予删除:不删除则遍历与容量统计均会被无效数据污染
|
|
42
|
+
await this.#driver.del(full).catch(() => undefined);
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
return env.v;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 读取,不存在时返回默认值
|
|
49
|
+
* @param key 命名空间内的键
|
|
50
|
+
* @param fallback 默认值
|
|
51
|
+
* @returns 值或默认值
|
|
52
|
+
*/
|
|
53
|
+
async getOr(key, fallback) {
|
|
54
|
+
const value = await this.get(key);
|
|
55
|
+
return value === undefined ? fallback : value;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 写入
|
|
59
|
+
* @param key 命名空间内的键
|
|
60
|
+
* @param value 值,必须可 JSON 序列化
|
|
61
|
+
* @param opts 写入选项
|
|
62
|
+
*/
|
|
63
|
+
async set(key, value, opts) {
|
|
64
|
+
await this.#driver.set(this.#full(key), envelope(value, opts?.ttl));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 删除
|
|
68
|
+
* @param key 命名空间内的键
|
|
69
|
+
*/
|
|
70
|
+
async del(key) {
|
|
71
|
+
await this.#driver.del(this.#full(key));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 判断是否存在且未过期
|
|
75
|
+
* @param key 命名空间内的键
|
|
76
|
+
* @returns 是否存在
|
|
77
|
+
*/
|
|
78
|
+
async has(key) {
|
|
79
|
+
return (await this.get(key)) !== undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 原子自增
|
|
83
|
+
*
|
|
84
|
+
* 驱动提供原生 `incr` 就直接用;否则按键串行地读改写。
|
|
85
|
+
* @param key 命名空间内的键
|
|
86
|
+
* @param by 增量,默认 1
|
|
87
|
+
* @param opts 写入选项;`ttl` 只在键首次创建时生效(与 Redis 的 INCR 语义一致:
|
|
88
|
+
* 自增不会刷新过期时间,否则热点计数器永不过期)
|
|
89
|
+
* @returns 自增后的值
|
|
90
|
+
*/
|
|
91
|
+
async incr(key, by = 1, opts) {
|
|
92
|
+
const full = this.#full(key);
|
|
93
|
+
const expireAt = expiryOf(opts?.ttl);
|
|
94
|
+
if (this.#driver.incr)
|
|
95
|
+
return this.#driver.incr(full, by, expireAt);
|
|
96
|
+
return this.#queue.run(full, async () => {
|
|
97
|
+
const env = await this.#driver.get(full);
|
|
98
|
+
const alive = env !== undefined && !isExpired(env);
|
|
99
|
+
const current = alive && typeof env.v === "number" ? env.v : 0;
|
|
100
|
+
const next = current + by;
|
|
101
|
+
// 已存在的键保留原过期时间点,新建的键才套用传入的 ttl
|
|
102
|
+
const keep = alive ? env.e : expireAt;
|
|
103
|
+
await this.#driver.set(full, keep === undefined ? { v: next } : { v: next, e: keep });
|
|
104
|
+
return next;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 读取剩余存活毫秒数
|
|
109
|
+
* @param key 命名空间内的键
|
|
110
|
+
* @returns 剩余毫秒;永不过期返回 Infinity;不存在或已过期返回 -1
|
|
111
|
+
*/
|
|
112
|
+
async ttl(key) {
|
|
113
|
+
const env = await this.#driver.get(this.#full(key));
|
|
114
|
+
if (env === undefined || isExpired(env))
|
|
115
|
+
return -1;
|
|
116
|
+
if (env.e === undefined)
|
|
117
|
+
return Number.POSITIVE_INFINITY;
|
|
118
|
+
return env.e - Date.now();
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 遍历键(不含命名空间前缀)
|
|
122
|
+
* @param prefix 命名空间内的额外前缀
|
|
123
|
+
* @returns 键的异步迭代器
|
|
124
|
+
*/
|
|
125
|
+
async *keys(prefix = "") {
|
|
126
|
+
for await (const [key] of this.entries(prefix))
|
|
127
|
+
yield key;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 遍历键值
|
|
131
|
+
* @param prefix 命名空间内的额外前缀
|
|
132
|
+
* @returns 键值对的异步迭代器
|
|
133
|
+
*/
|
|
134
|
+
async *entries(prefix = "") {
|
|
135
|
+
const base = this.#full(prefix);
|
|
136
|
+
const expired = [];
|
|
137
|
+
try {
|
|
138
|
+
for await (const [full, env] of this.#driver.scan(base)) {
|
|
139
|
+
if (isExpired(env)) {
|
|
140
|
+
if (expired.length < SWEEP_LIMIT)
|
|
141
|
+
expired.push(full);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
yield [full.slice(this.prefix.length), env.v];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
// 在迭代结束后再删:遍历过程中改动底层游标在部分驱动上是未定义行为。
|
|
149
|
+
// 提前 break 也会走到这里,已收集的过期键同样被清理。
|
|
150
|
+
if (expired.length > 0)
|
|
151
|
+
await this.#delMany(expired);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 清空(可按前缀)
|
|
156
|
+
* @param prefix 命名空间内的额外前缀,省略则清空整个命名空间
|
|
157
|
+
* @returns 删除的键数量
|
|
158
|
+
*/
|
|
159
|
+
async clear(prefix = "") {
|
|
160
|
+
const base = this.#full(prefix);
|
|
161
|
+
const keys = [];
|
|
162
|
+
for await (const [full] of this.#driver.scan(base))
|
|
163
|
+
keys.push(full);
|
|
164
|
+
await this.#delMany(keys);
|
|
165
|
+
return keys.length;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* 派生子命名空间
|
|
169
|
+
* @param name 子命名空间名
|
|
170
|
+
* @returns 新的 KV 视图,与父级共享驱动与自增队列
|
|
171
|
+
* @throws 当名字为空或含分隔符时(否则两个不同的子空间可能拼出同一个前缀)
|
|
172
|
+
*/
|
|
173
|
+
sub(name) {
|
|
174
|
+
if (name === "")
|
|
175
|
+
throw new Error("子命名空间名不能为空");
|
|
176
|
+
if (name.includes(SEP))
|
|
177
|
+
throw new Error(`子命名空间名不能含 "${SEP}":${name}`);
|
|
178
|
+
return new Kv(this.#driver, `${this.prefix}${name}${SEP}`, this.#queue);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* 拼出完整键
|
|
182
|
+
* @param key 命名空间内的键
|
|
183
|
+
* @returns 完整键
|
|
184
|
+
*/
|
|
185
|
+
#full(key) {
|
|
186
|
+
return `${this.prefix}${key}`;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* 批量删除,能用 batch 就用 batch
|
|
190
|
+
* @param keys 完整键列表
|
|
191
|
+
*/
|
|
192
|
+
async #delMany(keys) {
|
|
193
|
+
if (keys.length === 0)
|
|
194
|
+
return;
|
|
195
|
+
if (this.#driver.batch) {
|
|
196
|
+
await this.#driver.batch(keys.map(key => ({ op: "del", key })));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
for (const key of keys)
|
|
200
|
+
await this.#driver.del(key);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* 判断信封是否已过期
|
|
205
|
+
* @param env 值信封
|
|
206
|
+
* @returns 是否过期
|
|
207
|
+
*/
|
|
208
|
+
export function isExpired(env) {
|
|
209
|
+
return env.e !== undefined && env.e <= Date.now();
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* 计算过期时间点
|
|
213
|
+
* @param ttl 存活时长
|
|
214
|
+
* @returns 毫秒时间戳;不过期时 undefined
|
|
215
|
+
*/
|
|
216
|
+
export function expiryOf(ttl) {
|
|
217
|
+
if (ttl === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
const ms = parseDuration(ttl, 0);
|
|
220
|
+
return ms > 0 ? Date.now() + ms : undefined;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* 组装值信封
|
|
224
|
+
* @param value 值
|
|
225
|
+
* @param ttl 存活时长
|
|
226
|
+
* @returns 值信封
|
|
227
|
+
*/
|
|
228
|
+
export function envelope(value, ttl) {
|
|
229
|
+
const e = expiryOf(ttl);
|
|
230
|
+
return e === undefined ? { v: value } : { v: value, e };
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=kv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.js","sourceRoot":"","sources":["../../src/store/kv.ts"],"names":[],"mappings":"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"}
|