@h-ai/cache 0.1.0-alpha.67 → 0.1.0-alpha.68

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/dist/index.d.ts CHANGED
@@ -9,14 +9,35 @@ import { HaiResult } from '@h-ai/core';
9
9
  * @module cache-config
10
10
  */
11
11
 
12
- /** Redis 集群节点配置 */
12
+ /**
13
+ * Redis 集群节点配置
14
+ * @example
15
+ * ```ts
16
+ * import { RedisClusterNodeSchema } from '@h-ai/cache'
17
+ * const config = RedisClusterNodeSchema.parse({ host: 'redis.internal', port: 6379 })
18
+ * ```
19
+ */
13
20
  declare const RedisClusterNodeSchema: z.ZodObject<{
14
21
  host: z.ZodString;
15
22
  port: z.ZodNumber;
16
23
  }, z.core.$strip>;
17
- /** Redis 集群节点类型 */
24
+ /**
25
+ * Redis 集群节点类型
26
+ * @example
27
+ * ```ts
28
+ * import type { RedisClusterNode } from '@h-ai/cache'
29
+ * const options: RedisClusterNode = { host: 'redis.internal', port: 6379 }
30
+ * ```
31
+ */
18
32
  type RedisClusterNode = z.infer<typeof RedisClusterNodeSchema>;
19
- /** Redis 哨兵模式配置 */
33
+ /**
34
+ * Redis 哨兵模式配置
35
+ * @example
36
+ * ```ts
37
+ * import { RedisSentinelConfigSchema } from '@h-ai/cache'
38
+ * const config = RedisSentinelConfigSchema.parse({ name: 'primary', sentinels: [{ host: 'sentinel.internal', port: 26379 }] })
39
+ * ```
40
+ */
20
41
  declare const RedisSentinelConfigSchema: z.ZodObject<{
21
42
  sentinels: z.ZodArray<z.ZodObject<{
22
43
  host: z.ZodString;
@@ -24,9 +45,23 @@ declare const RedisSentinelConfigSchema: z.ZodObject<{
24
45
  }, z.core.$strip>>;
25
46
  name: z.ZodString;
26
47
  }, z.core.$strip>;
27
- /** Redis 哨兵模式配置类型 */
48
+ /**
49
+ * Redis 哨兵模式配置类型
50
+ * @example
51
+ * ```ts
52
+ * import type { RedisSentinelConfig } from '@h-ai/cache'
53
+ * const options: RedisSentinelConfig = { name: 'primary', sentinels: [{ host: 'sentinel.internal', port: 26379 }] }
54
+ * ```
55
+ */
28
56
  type RedisSentinelConfig = z.infer<typeof RedisSentinelConfigSchema>;
29
- /** 内存缓存配置(仅用于开发/测试,不支持跨进程共享) */
57
+ /**
58
+ * 内存缓存配置(仅用于开发/测试,不支持跨进程共享)
59
+ * @example
60
+ * ```ts
61
+ * import { MemoryConfigSchema } from '@h-ai/cache'
62
+ * const config = MemoryConfigSchema.parse({ type: 'memory' })
63
+ * ```
64
+ */
30
65
  declare const MemoryConfigSchema: z.ZodObject<{
31
66
  type: z.ZodLiteral<"memory">;
32
67
  }, z.core.$strip>;
@@ -34,6 +69,11 @@ declare const MemoryConfigSchema: z.ZodObject<{
34
69
  * Redis 缓存配置
35
70
  *
36
71
  * 连接优先级:url > cluster > sentinel > host
72
+ * @example
73
+ * ```ts
74
+ * import { RedisConfigSchema } from '@h-ai/cache'
75
+ * const config = RedisConfigSchema.parse({ type: 'redis', host: 'redis.internal' })
76
+ * ```
37
77
  */
38
78
  declare const RedisConfigSchema: z.ZodObject<{
39
79
  type: z.ZodLiteral<"redis">;
@@ -61,7 +101,14 @@ declare const RedisConfigSchema: z.ZodObject<{
61
101
  retryDelay: z.ZodDefault<z.ZodNumber>;
62
102
  readOnly: z.ZodDefault<z.ZodBoolean>;
63
103
  }, z.core.$strip>;
64
- /** 缓存配置 Schema;通过 type 字段区分 memory / redis */
104
+ /**
105
+ * 缓存配置 Schema;通过 type 字段区分 memory / redis
106
+ * @example
107
+ * ```ts
108
+ * import { CacheConfigSchema } from '@h-ai/cache'
109
+ * const config = CacheConfigSchema.parse({ type: 'redis', host: 'redis.internal' })
110
+ * ```
111
+ */
65
112
  declare const CacheConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
66
113
  type: z.ZodLiteral<"memory">;
67
114
  }, z.core.$strip>, z.ZodObject<{
@@ -90,11 +137,35 @@ declare const CacheConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
90
137
  retryDelay: z.ZodDefault<z.ZodNumber>;
91
138
  readOnly: z.ZodDefault<z.ZodBoolean>;
92
139
  }, z.core.$strip>], "type">;
93
- /** 缓存配置类型(Zod parse 后的完整类型,所有默认值已填充) */
140
+ /**
141
+ * 缓存配置类型(Zod parse 后的完整类型,所有默认值已填充)
142
+ * @example
143
+ * ```ts
144
+ * import { CacheConfigSchema, type CacheConfig } from '@h-ai/cache'
145
+ * const config: CacheConfig = CacheConfigSchema.parse({ type: 'redis', host: 'redis.internal' })
146
+ * ```
147
+ */
94
148
  type CacheConfig = z.infer<typeof CacheConfigSchema>;
95
- /** 缓存配置输入类型(Zod parse 前,允许省略带默认值的字段) */
149
+ /**
150
+ * 缓存配置输入类型(Zod parse 前,允许省略带默认值的字段)
151
+ * @example
152
+ * ```ts
153
+ * import type { CacheConfigInput } from '@h-ai/cache'
154
+ * const options: CacheConfigInput = { type: 'redis', host: 'redis.internal', keyPrefix: 'orders:' }
155
+ * ```
156
+ */
96
157
  type CacheConfigInput = z.input<typeof CacheConfigSchema>;
97
158
 
159
+ /**
160
+ * 缓存连接、序列化、输入与分布式操作的稳定错误定义。
161
+ * @example
162
+ * ```ts
163
+ * import { HaiCacheError } from '@h-ai/cache'
164
+ * import { err } from '@h-ai/core'
165
+ * const failure = err(HaiCacheError.INVALID_SET_OPTIONS, 'Conflicting expiry options')
166
+ * if (!failure.success) failure.error.code
167
+ * ```
168
+ */
98
169
  declare const HaiCacheError: {
99
170
  readonly CONNECTION_FAILED: _h_ai_core.HaiErrorDef;
100
171
  readonly OPERATION_FAILED: _h_ai_core.HaiErrorDef;
@@ -105,38 +176,82 @@ declare const HaiCacheError: {
105
176
  readonly NOT_INITIALIZED: _h_ai_core.HaiErrorDef;
106
177
  readonly UNSUPPORTED_TYPE: _h_ai_core.HaiErrorDef;
107
178
  readonly CONFIG_ERROR: _h_ai_core.HaiErrorDef;
179
+ readonly INVALID_SCAN: _h_ai_core.HaiErrorDef;
180
+ readonly SCAN_TOPOLOGY_CHANGED: _h_ai_core.HaiErrorDef;
181
+ readonly CROSS_SLOT: _h_ai_core.HaiErrorDef;
182
+ readonly INVALID_SET_OPTIONS: _h_ai_core.HaiErrorDef;
108
183
  };
109
184
  /**
110
185
  * 可缓存的值类型
111
186
  *
112
187
  * 说明:`object` 包含普通对象与数组;函数、Symbol、BigInt 等不建议直接缓存。
188
+ * @example
189
+ * ```ts
190
+ * import type { CacheValue } from '@h-ai/cache'
191
+ * const options: CacheValue = { id: 'order-1', paid: false }
192
+ * ```
113
193
  */
114
194
  type CacheValue = string | number | boolean | object | null;
115
- /** 缓存设置选项 */
195
+ /**
196
+ * SET 选项;四种期限彼此互斥且与 keepTtl 互斥,nx/xx 互斥。
197
+ * @example
198
+ * ```ts
199
+ * import type { SetOptions } from '@h-ai/cache'
200
+ * const options: SetOptions = { px: 60_000, nx: true }
201
+ * ```
202
+ */
116
203
  interface SetOptions {
117
- /** 过期时间(秒) */
204
+ /** 过期时间(正安全整数秒),零/负数无效。 */
118
205
  ex?: number;
119
- /** 过期时间(毫秒) */
206
+ /** 过期时间(正安全整数毫秒),零/负数无效。 */
120
207
  px?: number;
121
- /** 过期时间点(Unix 时间戳,秒) */
208
+ /** Unix 正安全整数秒;过去时间会立即过期,乘1000后须仍为安全整数。 */
122
209
  exat?: number;
123
- /** 过期时间点(Unix 时间戳,毫秒) */
210
+ /** Unix 正安全整数毫秒;过去时间会立即过期。 */
124
211
  pxat?: number;
125
212
  /** 仅在键不存在时设置 */
126
213
  nx?: boolean;
127
214
  /** 仅在键存在时设置 */
128
215
  xx?: boolean;
129
- /** 保留原有的 TTL(与 ex/px/exat/pxat 互斥,冲突时以后端实现行为为准) */
216
+ /** 保留原 TTL;新键无 TTL,与所有显式期限互斥。 */
130
217
  keepTtl?: boolean;
131
218
  }
132
- /** 扫描选项 */
219
+ /**
220
+ * 扫描选项
221
+ * @example
222
+ * ```ts
223
+ * import type { ScanOptions } from '@h-ai/cache'
224
+ * const options: ScanOptions = { match: 'orders:*', count: 100 }
225
+ * ```
226
+ */
133
227
  interface ScanOptions {
134
228
  /** 匹配模式 */
135
229
  match?: string;
136
230
  /** 每次扫描数量 */
137
231
  count?: number;
138
232
  }
139
- /** 有序集合成员(score + member 对) */
233
+ /**
234
+ * 条件替换的过期策略;px 与 keepTtl 互斥,省略时新值永久保存。
235
+ * @example
236
+ * ```ts
237
+ * import type { CompareAndSwapOptions } from '@h-ai/cache'
238
+ * const options: CompareAndSwapOptions = { px: 60_000 }
239
+ * ```
240
+ */
241
+ interface CompareAndSwapOptions {
242
+ /** 新值存续的正整数毫秒数。 */
243
+ px?: number;
244
+ /** 成功替换时保留已有 TTL;原键不存在时新值无 TTL。 */
245
+ keepTtl?: boolean;
246
+ }
247
+ /**
248
+ * 有序集合成员(score + member 对)
249
+ * @example
250
+ * ```ts
251
+ * import type { ZMember } from '@h-ai/cache'
252
+ * const options: ZMember = { score: 100, member: 'player-1' }
253
+ * ```
254
+ */
140
255
  interface ZMember {
141
256
  /** 分数,用于排序 */
142
257
  score: number;
@@ -145,21 +260,56 @@ interface ZMember {
145
260
  }
146
261
  /**
147
262
  * 基础键值操作接口
148
- *
149
263
  * @example
150
264
  * ```ts
151
- * await cache.kv.set('key', { name: '张三' }, { ex: 3600 })
152
- * const result = await cache.kv.get<{ name: string }>('key')
265
+ * import type { KvOperations } from '@h-ai/cache'
266
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
267
+ * async function example(operations: KvOperations) {
268
+ * const claimed = await operations.set('orders:claim', 'worker-1', { nx: true, px: 60_000 })
269
+ * if (!claimed.success) return claimed
270
+ * if (!claimed.data) return 'already claimed'
271
+ * const read = await operations.get<string>('orders:claim')
272
+ * return read.success ? read.data : read.error.message
273
+ * }
153
274
  * ```
154
275
  */
155
276
  interface KvOperations {
156
277
  /** 获取值;键不存在时返回 null */
157
278
  get: <T = CacheValue>(key: string) => Promise<HaiResult<T | null>>;
158
- /** 设置值;可通过 options 控制过期时间、NX/XX 条件等 */
159
- set: (key: string, value: CacheValue, options?: SetOptions) => Promise<HaiResult<void>>;
160
- /** 删除一个或多个键;返回实际删除的数量 */
279
+ /**
280
+ * 设置 JSON 快照,返回实际是否写入;NX/XX 未命中为 success:true/data:false,原值与TTL不变。
281
+ * 参数非法返回 INVALID_SET_OPTIONS;省略期限永久保存,keepTtl 显式保留原期限。
282
+ * @example
283
+ * ```ts
284
+ * import type { KvOperations } from '@h-ai/cache'
285
+ * async function reserve(kv: KvOperations) {
286
+ * const applied = await kv.set('orders:claim', 'worker-1', { nx: true, px: 1000 })
287
+ * return applied.success ? applied.data : applied.error.message
288
+ * }
289
+ * ```
290
+ */
291
+ set: (key: string, value: CacheValue, options?: SetOptions) => Promise<HaiResult<boolean>>;
292
+ /**
293
+ * 对单个 key 原子比较 JSON 序列化值并替换;比较失败返回 false,不修改值/TTL。
294
+ * expected=undefined 表示键不存在;value=undefined 表示删除,null 是实际 JSON 值。
295
+ * 适合跨节点状态版本更新,Cluster 只涉及一个 slot;调用方必须检查 success 和 data。
296
+ * @example
297
+ * ```ts
298
+ * import type { KvOperations } from '@h-ai/cache'
299
+ * async function advance(kv: KvOperations) {
300
+ * const read = await kv.get<number>('orders:version')
301
+ * if (!read.success) return read
302
+ * const expected = read.data ?? undefined
303
+ * const changed = await kv.compareAndSwap('orders:version', expected, (expected ?? 0) + 1, { px: 60_000 })
304
+ * // data=false 时需要重新读取后再决定是否重试,不能按成功提交处理。
305
+ * return changed.success ? changed.data : changed.error.message
306
+ * }
307
+ * ```
308
+ */
309
+ compareAndSwap: (key: string, expected: CacheValue | undefined, value: CacheValue | undefined, options?: CompareAndSwapOptions) => Promise<HaiResult<boolean>>;
310
+ /** 删除一个或多个键;返回实际删除的数量。Cluster 跨 slot 按独立键有界执行,失败可能已有部分删除,重试幂等。 */
161
311
  del: (...keys: string[]) => Promise<HaiResult<number>>;
162
- /** 检查一个或多个键是否存在;返回存在的数量 */
312
+ /** 检查一个或多个键是否存在;返回存在的数量。Cluster 跨 slot 独立读取,不保证同一时刻快照。 */
163
313
  exists: (...keys: string[]) => Promise<HaiResult<number>>;
164
314
  /** 设置过期时间(秒) */
165
315
  expire: (key: string, seconds: number) => Promise<HaiResult<boolean>>;
@@ -177,12 +327,25 @@ interface KvOperations {
177
327
  decr: (key: string) => Promise<HaiResult<number>>;
178
328
  /** 自减指定值;键不存在时从 0 开始 */
179
329
  decrBy: (key: string, decrement: number) => Promise<HaiResult<number>>;
180
- /** 批量获取;不存在的键对应位置返回 null */
330
+ /** 批量获取;不存在的键对应位置返回 null。Cluster 跨 slot 保留输入顺序,不保证同一时刻快照。 */
181
331
  mget: <T = CacheValue>(...keys: string[]) => Promise<HaiResult<(T | null)[]>>;
182
- /** 批量设置键值对 */
332
+ /** 原子批量设置;Cluster 中所有 key 必须同 slot,可使用共同的 {hash-tag}。 */
183
333
  mset: (entries: Array<[string, CacheValue]>) => Promise<HaiResult<void>>;
184
- /** 游标扫描键;返回 [下一游标, 匹配的键列表],游标为 0 时表示遍历完成 */
185
- scan: (cursor: number, options?: ScanOptions) => Promise<HaiResult<[number, string[]]>>;
334
+ /**
335
+ * 游标扫描逻辑 key,首次传 '0',后续原样传回不透明字符串;'0' 表示完成。
336
+ * Cluster 遍历全部主节点,拓扑/match/keyPrefix 变化返回 SCAN_TOPOLOGY_CHANGED,须重启遍历。
337
+ * 与 Redis SCAN 一致,不提供快照,可能返回重复项;调用方按需去重。
338
+ * @example
339
+ * ```ts
340
+ * import type { KvOperations } from '@h-ai/cache'
341
+ * async function readPage(kv: KvOperations, cursor = '0') {
342
+ * const page = await kv.scan(cursor, { match: 'orders:*', count: 100 })
343
+ * if (!page.success) return page
344
+ * return { next: page.data[0], keys: page.data[1] }
345
+ * }
346
+ * ```
347
+ */
348
+ scan: (cursor: string, options?: ScanOptions) => Promise<HaiResult<[string, string[]]>>;
186
349
  /** 获取匹配模式的所有键(慎用,生产环境请用 scan 迭代) */
187
350
  keys: (pattern: string) => Promise<HaiResult<string[]>>;
188
351
  /** 获取键的数据类型;不存在时返回 "none" */
@@ -190,11 +353,16 @@ interface KvOperations {
190
353
  }
191
354
  /**
192
355
  * Hash 操作接口
193
- *
194
356
  * @example
195
357
  * ```ts
196
- * await cache.hash.hset('user:1', { name: '张三', age: 25 })
197
- * const name = await cache.hash.hget<string>('user:1', 'name')
358
+ * import type { HashOperations } from '@h-ai/cache'
359
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
360
+ * async function example(operations: HashOperations) {
361
+ * const written = await operations.hset('orders:1', { status: 'pending', version: 1 })
362
+ * if (!written.success) return written
363
+ * const status = await operations.hget<string>('orders:1', 'status')
364
+ * return status.success ? status.data : status.error.message
365
+ * }
198
366
  * ```
199
367
  */
200
368
  interface HashOperations {
@@ -221,11 +389,16 @@ interface HashOperations {
221
389
  }
222
390
  /**
223
391
  * List 操作接口
224
- *
225
392
  * @example
226
393
  * ```ts
227
- * await cache.list.lpush('queue', 'task1', 'task2')
228
- * const item = await cache.list.rpop<string>('queue')
394
+ * import type { ListOperations } from '@h-ai/cache'
395
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
396
+ * async function example(operations: ListOperations) {
397
+ * const queued = await operations.rpush('orders:queue', 'order-1')
398
+ * if (!queued.success) return queued
399
+ * const next = await operations.lpop<string>('orders:queue')
400
+ * return next.success ? next.data : next.error.message
401
+ * }
229
402
  * ```
230
403
  */
231
404
  interface ListOperations {
@@ -247,18 +420,23 @@ interface ListOperations {
247
420
  lset: (key: string, index: number, value: CacheValue) => Promise<HaiResult<void>>;
248
421
  /** 保留指定范围的元素,范围外的元素被删除 */
249
422
  ltrim: (key: string, start: number, stop: number) => Promise<HaiResult<void>>;
250
- /** 阻塞式从左侧弹出;返回 [key, value] 或超时返回 null。memory 实现为非阻塞立即返回。 */
423
+ /** 阻塞式从左侧弹出;返回 [key, value] 或超时返回 null。Cluster 多键须同 slot;memory 非阻塞立即返回。 */
251
424
  blpop: <T = CacheValue>(timeout: number, ...keys: string[]) => Promise<HaiResult<[string, T] | null>>;
252
- /** 阻塞式从右侧弹出;返回 [key, value] 或超时返回 null。memory 实现为非阻塞立即返回。 */
425
+ /** 阻塞式从右侧弹出;返回 [key, value] 或超时返回 null。Cluster 多键须同 slot;memory 非阻塞立即返回。 */
253
426
  brpop: <T = CacheValue>(timeout: number, ...keys: string[]) => Promise<HaiResult<[string, T] | null>>;
254
427
  }
255
428
  /**
256
429
  * Set 操作接口
257
- *
258
430
  * @example
259
431
  * ```ts
260
- * await cache.set_.sadd('tags', 'redis', 'cache')
261
- * const members = await cache.set_.smembers<string>('tags')
432
+ * import type { SetOperations } from '@h-ai/cache'
433
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
434
+ * async function example(operations: SetOperations) {
435
+ * const added = await operations.sadd('orders:tags', 'paid', 'priority')
436
+ * if (!added.success) return added
437
+ * const members = await operations.smembers<string>('orders:tags')
438
+ * return members.success ? members.data : members.error.message
439
+ * }
262
440
  * ```
263
441
  */
264
442
  interface SetOperations {
@@ -276,20 +454,25 @@ interface SetOperations {
276
454
  srandmember: <T = CacheValue>(key: string, count?: number) => Promise<HaiResult<T | T[] | null>>;
277
455
  /** 随机弹出成员(会从集合中移除);不指定 count 返回单个值,指定 count 返回数组;空集合返回 null */
278
456
  spop: <T = CacheValue>(key: string, count?: number) => Promise<HaiResult<T | T[] | null>>;
279
- /** 集合交集;任一 key 不存在时返回空数组 */
457
+ /** 集合交集;任一 key 不存在时返回空数组。Cluster 多键须同 slot,否则返回 CROSS_SLOT。 */
280
458
  sinter: <T = CacheValue>(...keys: string[]) => Promise<HaiResult<T[]>>;
281
- /** 集合并集 */
459
+ /** 集合并集;Cluster 多键须同 slot,否则返回 CROSS_SLOT。 */
282
460
  sunion: <T = CacheValue>(...keys: string[]) => Promise<HaiResult<T[]>>;
283
- /** 集合差集(第一个集合减去其余集合) */
461
+ /** 集合差集(第一个集合减去其余集合);Cluster 多键须同 slot,否则返回 CROSS_SLOT。 */
284
462
  sdiff: <T = CacheValue>(...keys: string[]) => Promise<HaiResult<T[]>>;
285
463
  }
286
464
  /**
287
465
  * 有序集合操作接口
288
- *
289
466
  * @example
290
467
  * ```ts
291
- * await cache.zset.zadd('rank', { score: 100, member: 'player1' })
292
- * const top = await cache.zset.zrevrange('rank', 0, 9, true)
468
+ * import type { ZSetOperations } from '@h-ai/cache'
469
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
470
+ * async function example(operations: ZSetOperations) {
471
+ * const added = await operations.zadd('orders:rank', { member: 'order-1', score: 100 })
472
+ * if (!added.success) return added
473
+ * const top = await operations.zrevrange('orders:rank', 0, 9, true)
474
+ * return top.success ? top.data : top.error.message
475
+ * }
293
476
  * ```
294
477
  */
295
478
  interface ZSetOperations {
@@ -328,16 +511,16 @@ interface ZSetOperations {
328
511
  * 分布式锁操作接口
329
512
  *
330
513
  * 基于 SET NX EX 模式实现分布式互斥锁,适用于多节点部署场景。
331
- *
332
514
  * @example
333
515
  * ```ts
334
- * const acquired = await cache.lock.acquire('my-lock', { ttl: 30 })
335
- * if (acquired.success && acquired.data) {
336
- * try {
337
- * // 执行受保护操作
338
- * } finally {
339
- * await cache.lock.release('my-lock')
340
- * }
516
+ * import type { LockOperations } from '@h-ai/cache'
517
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
518
+ * async function example(operations: LockOperations) {
519
+ * const acquired = await operations.acquire('orders:lock', { ttl: 30 })
520
+ * if (!acquired.success || !acquired.data) return acquired
521
+ * const released = await operations.release('orders:lock', acquired.data)
522
+ * // owner 不是 fencing token;业务最终写入仍需自己的数据库/CAS条件。
523
+ * return released.success ? released.data : released.error.message
341
524
  * }
342
525
  * ```
343
526
  */
@@ -345,23 +528,25 @@ interface LockOperations {
345
528
  /**
346
529
  * 尝试获取分布式锁
347
530
  *
348
- * 通过 SET NX EX 原子操作实现。获锁成功返回 true,锁已被持有返回 false。
531
+ * 通过 SET NX EX 原子操作实现。每次生成不可复用的所有权凭据;占用时返回 null。
532
+ * owner 仅用于租约续期/释放,不是资源的 fencing token;暂停/超时后旧操作仍可能继续。
533
+ * 最终资源写入必须自行使用 CAS/代际条件或数据库事务约束,不能只检查续期或返回失败。
349
534
  *
350
535
  * @param key - 锁键名
351
536
  * @param options - 锁选项
352
- * @returns true 表示获锁成功,false 表示锁已被其他持有者持有
537
+ * @returns 获锁成功返回唯一凭据,锁占用时返回 null
353
538
  */
354
- acquire: (key: string, options?: LockOptions) => Promise<HaiResult<boolean>>;
539
+ acquire: (key: string, options?: LockOptions) => Promise<HaiResult<string | null>>;
355
540
  /**
356
541
  * 释放分布式锁
357
542
  *
358
543
  * 仅当锁由当前持有者持有时才释放(通过 owner 比对),防止误释放他人的锁。
359
544
  *
360
545
  * @param key - 锁键名
361
- * @param owner - 锁持有者标识(须与 acquire 时一致);未传则强制释放
546
+ * @param owner - 本次 acquire 返回的唯一凭据,不能使用节点 ID
362
547
  * @returns true 表示释放成功,false 表示锁不存在或非当前持有者
363
548
  */
364
- release: (key: string, owner?: string) => Promise<HaiResult<boolean>>;
549
+ release: (key: string, owner: string) => Promise<HaiResult<boolean>>;
365
550
  /**
366
551
  * 检查锁是否被持有
367
552
  *
@@ -376,22 +561,38 @@ interface LockOperations {
376
561
  *
377
562
  * @param key - 锁键名
378
563
  * @param ttl - 新的过期时间(秒)
379
- * @param owner - 锁持有者标识;未传则直接续期
564
+ * @param owner - 本次 acquire 返回的唯一凭据
380
565
  * @returns true 表示续期成功,false 表示锁不存在或非当前持有者
381
566
  */
382
- extend: (key: string, ttl: number, owner?: string) => Promise<HaiResult<boolean>>;
567
+ extend: (key: string, ttl: number, owner: string) => Promise<HaiResult<boolean>>;
383
568
  }
384
- /** 分布式锁选项 */
569
+ /**
570
+ * 分布式锁选项
571
+ * @example
572
+ * ```ts
573
+ * import type { LockOptions } from '@h-ai/cache'
574
+ * const options: LockOptions = { ttl: 30 }
575
+ * ```
576
+ */
385
577
  interface LockOptions {
386
578
  /** 锁过期时间(秒);默认 30 */
387
579
  ttl?: number;
388
- /** 锁持有者标识;默认 'default'(多节点部署时建议设置固定值以便审计) */
389
- owner?: string;
390
580
  }
391
581
  /**
392
582
  * 复合缓存操作接口,聚合所有数据结构的操作子接口
393
583
  *
394
584
  * 通过 `cache.kv` / `cache.hash` / `cache.list` / `cache.set_` / `cache.zset` / `cache.lock` 分别访问
585
+ * @example
586
+ * ```ts
587
+ * import type { CacheCompositeOperations } from '@h-ai/cache'
588
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
589
+ * async function example(operations: CacheCompositeOperations) {
590
+ * const health = await operations.ping()
591
+ * if (!health.success) return health
592
+ * const result = await operations.kv.get<string>('orders:1')
593
+ * return result.success ? result.data : result.error.message
594
+ * }
595
+ * ```
395
596
  */
396
597
  interface CacheCompositeOperations {
397
598
  /** KV 操作 */
@@ -411,15 +612,16 @@ interface CacheCompositeOperations {
411
612
  }
412
613
  /**
413
614
  * 缓存函数接口
414
- *
415
615
  * @example
416
616
  * ```ts
417
- * import { cache } from '@h-ai/cache'
418
- *
419
- * await cache.init({ type: 'redis', host: 'localhost' })
420
- * await cache.kv.set('key', 'value', { ex: 3600 })
421
- * const result = await cache.kv.get('key')
422
- * await cache.close()
617
+ * import type { CacheFunctions } from '@h-ai/cache'
618
+ * // 传入已初始化 cache 的对应操作;连接生命周期由创建者管理。
619
+ * async function example(operations: CacheFunctions) {
620
+ * const initialized = await operations.init({ type: 'redis', host: 'localhost' })
621
+ * if (!initialized.success) return initialized
622
+ * try { return await operations.kv.get<string>('orders:1') }
623
+ * finally { const closed = await operations.close(); if (!closed.success) return closed }
624
+ * }
423
625
  * ```
424
626
  */
425
627
  interface CacheFunctions extends CacheCompositeOperations {
@@ -429,23 +631,14 @@ interface CacheFunctions extends CacheCompositeOperations {
429
631
  readonly config: CacheConfig | null;
430
632
  /** 是否已初始化并连接 */
431
633
  readonly isInitialized: boolean;
432
- /** 关闭连接并清理资源;未初始化时调用安全无副作用 */
433
- close: () => Promise<void>;
434
- }
435
- /**
436
- * 缓存 Provider 接口
437
- *
438
- * 由具体实现(memory / redis)提供;上层通过 cache-main 统一管理生命周期。
439
- */
440
- interface CacheProvider extends CacheCompositeOperations {
441
- /** Provider 名称(如 'memory' / 'redis') */
442
- readonly name: string;
443
- /** 连接缓存服务;config 已经过 Zod Schema 校验 */
444
- connect: (config: CacheConfig) => Promise<HaiResult<void>>;
445
- /** 关闭连接并释放资源 */
446
- close: () => Promise<void>;
447
- /** 是否处于已连接状态 */
448
- isConnected: () => boolean;
634
+ /**
635
+ * 关闭连接并清理资源;失败时停止提供业务操作并保留资源,可再次 close/init 重试。
636
+ * @returns 资源全部释放时成功;释放失败时返回 CONNECTION_FAILED。
637
+ * @example
638
+ * const result = await cache.close()
639
+ * if (!result.success) await cache.close()
640
+ */
641
+ close: () => Promise<HaiResult<void>>;
449
642
  }
450
643
 
451
644
  /**
@@ -457,17 +650,22 @@ interface CacheProvider extends CacheCompositeOperations {
457
650
 
458
651
  /**
459
652
  * 缓存服务对象
460
- *
461
653
  * @example
462
654
  * ```ts
463
655
  * import { cache } from '@h-ai/cache'
464
- *
465
- * await cache.init({ type: 'redis', host: 'localhost', port: 6379 })
466
- * await cache.kv.set('user:1', { name: '张三' }, { ex: 3600 })
467
- * const result = await cache.kv.get<{ name: string }>('user:1')
468
- * await cache.close()
656
+ * import { core } from '@h-ai/core'
657
+ * const initialized = await cache.init({ type: 'redis', host: 'localhost' })
658
+ * if (initialized.success) {
659
+ * try {
660
+ * const claimed = await cache.kv.set('orders:claim', 'worker-1', { nx: true, px: 60_000 })
661
+ * if (claimed.success && claimed.data) core.logger.info('Claim created')
662
+ * } finally {
663
+ * const closed = await cache.close()
664
+ * if (!closed.success) core.logger.error('Cache cleanup pending', { code: closed.error.code })
665
+ * }
666
+ * }
469
667
  * ```
470
668
  */
471
669
  declare const cache: CacheFunctions;
472
670
 
473
- export { type CacheCompositeOperations, type CacheConfig, type CacheConfigInput, CacheConfigSchema, type CacheFunctions, type CacheProvider, type CacheValue, HaiCacheError, type HashOperations, type KvOperations, type ListOperations, type LockOperations, type LockOptions, MemoryConfigSchema, type RedisClusterNode, RedisClusterNodeSchema, RedisConfigSchema, type RedisSentinelConfig, RedisSentinelConfigSchema, type ScanOptions, type SetOperations, type SetOptions, type ZMember, type ZSetOperations, cache };
671
+ export { type CacheCompositeOperations, type CacheConfig, type CacheConfigInput, CacheConfigSchema, type CacheFunctions, type CacheValue, type CompareAndSwapOptions, HaiCacheError, type HashOperations, type KvOperations, type ListOperations, type LockOperations, type LockOptions, MemoryConfigSchema, type RedisClusterNode, RedisClusterNodeSchema, RedisConfigSchema, type RedisSentinelConfig, RedisSentinelConfigSchema, type ScanOptions, type SetOperations, type SetOptions, type ZMember, type ZSetOperations, cache };