@chatcops/store-redis 0.0.0-stage → 0.2.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.
@@ -0,0 +1,581 @@
1
+ import { ConflictError, } from '@chatcops/core';
2
+ import { decodeEvalResult, formatSlotPrefix, normalizeList } from './adapter.js';
3
+ const GET_SCRIPT = `
4
+ local meta = redis.call('HGETALL', KEYS[1])
5
+ if #meta == 0 then
6
+ return nil
7
+ end
8
+ local messages = redis.call('LRANGE', KEYS[2], 0, -1)
9
+ local metaJson = cjson.encode(meta)
10
+ local msgsJson = '[]'
11
+ if #messages > 0 then
12
+ msgsJson = cjson.encode(messages)
13
+ end
14
+ return '{"meta":' .. metaJson .. ',"messages":' .. msgsJson .. '}'
15
+ `;
16
+ const SAVE_SCRIPT = `
17
+ local now = tonumber(ARGV[3])
18
+ local ttl = tonumber(ARGV[4])
19
+
20
+ if ttl > 0 then
21
+ redis.call('ZREMRANGEBYSCORE', KEYS[3], '-inf', '(' .. (now - ttl))
22
+ end
23
+
24
+ local currentVersion = redis.call('HGET', KEYS[1], 'version')
25
+ local newVersion = 1
26
+ if currentVersion then
27
+ newVersion = tonumber(currentVersion) + 1
28
+ end
29
+
30
+ local createdAt = tonumber(ARGV[2])
31
+ if not createdAt or createdAt == 0 then
32
+ local currentCreatedAt = redis.call('HGET', KEYS[1], 'createdAt')
33
+ if currentCreatedAt then
34
+ createdAt = tonumber(currentCreatedAt)
35
+ else
36
+ createdAt = now
37
+ end
38
+ end
39
+
40
+ local updatedAt = now
41
+
42
+ redis.call('DEL', KEYS[1], KEYS[2])
43
+
44
+ redis.call('HSET', KEYS[1], 'id', ARGV[1], 'version', newVersion, 'createdAt', createdAt, 'updatedAt', updatedAt)
45
+
46
+ local numMeta = tonumber(ARGV[5])
47
+ local metaOffset = 5
48
+ for i = 1, numMeta do
49
+ local k = ARGV[metaOffset + (i - 1) * 2 + 1]
50
+ local v = ARGV[metaOffset + (i - 1) * 2 + 2]
51
+ redis.call('HSET', KEYS[1], 'meta:' .. k, v)
52
+ end
53
+
54
+ local msgStart = metaOffset + numMeta * 2 + 1
55
+ for i = msgStart, #ARGV do
56
+ redis.call('RPUSH', KEYS[2], ARGV[i])
57
+ end
58
+
59
+ if ttl <= 0 then
60
+ redis.call('DEL', KEYS[1], KEYS[2])
61
+ redis.call('ZREM', KEYS[3], ARGV[1])
62
+ else
63
+ redis.call('PEXPIRE', KEYS[1], ttl)
64
+ redis.call('PEXPIRE', KEYS[2], ttl)
65
+ redis.call('ZADD', KEYS[3], updatedAt, ARGV[1])
66
+ end
67
+
68
+ return newVersion
69
+ `;
70
+ const APPEND_SCRIPT = `
71
+ local now = tonumber(ARGV[3])
72
+ local ttl = tonumber(ARGV[4])
73
+
74
+ if ttl > 0 then
75
+ redis.call('ZREMRANGEBYSCORE', KEYS[3], '-inf', '(' .. (now - ttl))
76
+ end
77
+
78
+ local rawVersion = redis.call('HGET', KEYS[1], 'version')
79
+ local currentVersion = 0
80
+ if rawVersion then
81
+ currentVersion = tonumber(rawVersion)
82
+ end
83
+
84
+ local expectedVersionStr = ARGV[2]
85
+ if expectedVersionStr ~= '' then
86
+ local expectedVersion = tonumber(expectedVersionStr)
87
+ if expectedVersion ~= currentVersion then
88
+ return cjson.encode({ 'CONFLICT', tostring(currentVersion) })
89
+ end
90
+ end
91
+
92
+ local newVersion = currentVersion + 1
93
+
94
+ local createdAt = now
95
+ local rawCreatedAt = redis.call('HGET', KEYS[1], 'createdAt')
96
+ if rawCreatedAt then
97
+ createdAt = tonumber(rawCreatedAt)
98
+ end
99
+
100
+ redis.call('HSET', KEYS[1], 'id', ARGV[1], 'version', newVersion, 'createdAt', createdAt, 'updatedAt', now)
101
+
102
+ -- Shallow merge metadata fields directly into Redis hash fields without Lua cjson
103
+ local numMeta = tonumber(ARGV[5])
104
+ local metaOffset = 5
105
+ for i = 1, numMeta do
106
+ local k = ARGV[metaOffset + (i - 1) * 2 + 1]
107
+ local v = ARGV[metaOffset + (i - 1) * 2 + 2]
108
+ redis.call('HSET', KEYS[1], 'meta:' .. k, v)
109
+ end
110
+
111
+ local msgStart = metaOffset + numMeta * 2 + 1
112
+ for i = msgStart, #ARGV do
113
+ redis.call('RPUSH', KEYS[2], ARGV[i])
114
+ end
115
+
116
+ if ttl <= 0 then
117
+ redis.call('DEL', KEYS[1], KEYS[2])
118
+ redis.call('ZREM', KEYS[3], ARGV[1])
119
+ else
120
+ redis.call('PEXPIRE', KEYS[1], ttl)
121
+ redis.call('PEXPIRE', KEYS[2], ttl)
122
+ redis.call('ZADD', KEYS[3], now, ARGV[1])
123
+ end
124
+
125
+ return cjson.encode({ 'OK', tostring(newVersion) })
126
+ `;
127
+ const UPDATE_MESSAGE_SCRIPT = `
128
+ local now = tonumber(ARGV[4])
129
+ local ttl = tonumber(ARGV[5])
130
+
131
+ if ttl > 0 then
132
+ redis.call('ZREMRANGEBYSCORE', KEYS[3], '-inf', '(' .. (now - ttl))
133
+ end
134
+
135
+ local rawVersion = redis.call('HGET', KEYS[1], 'version')
136
+ if not rawVersion then
137
+ return 0
138
+ end
139
+
140
+ local msgs = redis.call('LRANGE', KEYS[2], 0, -1)
141
+ local targetId = ARGV[2]
142
+ local foundIndex = -1
143
+
144
+ for i, rawMsg in ipairs(msgs) do
145
+ local decoded = cjson.decode(rawMsg)
146
+ if decoded['id'] == targetId then
147
+ foundIndex = i - 1
148
+ break
149
+ end
150
+ end
151
+
152
+ if foundIndex == -1 then
153
+ return 0
154
+ end
155
+
156
+ redis.call('LSET', KEYS[2], foundIndex, ARGV[3])
157
+
158
+ local newVersion = tonumber(rawVersion) + 1
159
+
160
+ redis.call('HSET', KEYS[1], 'version', newVersion, 'updatedAt', now)
161
+ if ttl <= 0 then
162
+ redis.call('DEL', KEYS[1], KEYS[2])
163
+ redis.call('ZREM', KEYS[3], ARGV[1])
164
+ else
165
+ redis.call('PEXPIRE', KEYS[1], ttl)
166
+ redis.call('PEXPIRE', KEYS[2], ttl)
167
+ redis.call('ZADD', KEYS[3], now, ARGV[1])
168
+ end
169
+
170
+ return 1
171
+ `;
172
+ const REMOVE_MESSAGE_SCRIPT = `
173
+ local now = tonumber(ARGV[3])
174
+ local ttl = tonumber(ARGV[4])
175
+
176
+ if ttl > 0 then
177
+ redis.call('ZREMRANGEBYSCORE', KEYS[3], '-inf', '(' .. (now - ttl))
178
+ end
179
+
180
+ local rawVersion = redis.call('HGET', KEYS[1], 'version')
181
+ if not rawVersion then
182
+ return 0
183
+ end
184
+
185
+ local msgs = redis.call('LRANGE', KEYS[2], 0, -1)
186
+ local targetId = ARGV[2]
187
+ local found = false
188
+ local remaining = {}
189
+
190
+ for _, rawMsg in ipairs(msgs) do
191
+ local decoded = cjson.decode(rawMsg)
192
+ if decoded['id'] == targetId then
193
+ found = true
194
+ else
195
+ table.insert(remaining, rawMsg)
196
+ end
197
+ end
198
+
199
+ if not found then
200
+ return 0
201
+ end
202
+
203
+ redis.call('DEL', KEYS[2])
204
+ for _, m in ipairs(remaining) do
205
+ redis.call('RPUSH', KEYS[2], m)
206
+ end
207
+
208
+ local newVersion = tonumber(rawVersion) + 1
209
+
210
+ redis.call('HSET', KEYS[1], 'version', newVersion, 'updatedAt', now)
211
+ if ttl <= 0 then
212
+ redis.call('DEL', KEYS[1], KEYS[2])
213
+ redis.call('ZREM', KEYS[3], ARGV[1])
214
+ else
215
+ redis.call('PEXPIRE', KEYS[1], ttl)
216
+ redis.call('PEXPIRE', KEYS[2], ttl)
217
+ redis.call('ZADD', KEYS[3], now, ARGV[1])
218
+ end
219
+
220
+ return 1
221
+ `;
222
+ const DELETE_SCRIPT = `
223
+ redis.call('DEL', KEYS[1], KEYS[2])
224
+ redis.call('ZREM', KEYS[3], ARGV[1])
225
+ return 1
226
+ `;
227
+ const PURGE_IDS_SCRIPT = `
228
+ local ids = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', '(' .. ARGV[1], 'LIMIT', 0, tonumber(ARGV[2]))
229
+ if #ids == 0 then
230
+ return '[]'
231
+ end
232
+ return cjson.encode(ids)
233
+ `;
234
+ const PURGE_EXEC_SCRIPT = `
235
+ local zsetKey = KEYS[1]
236
+ local numIds = tonumber(ARGV[1])
237
+
238
+ for i = 2, #KEYS do
239
+ redis.call('DEL', KEYS[i])
240
+ end
241
+
242
+ for i = 1, numIds do
243
+ redis.call('ZREM', zsetKey, ARGV[1 + i])
244
+ end
245
+
246
+ return numIds
247
+ `;
248
+ const LIST_IDS_SCRIPT = `
249
+ local zsetKey = KEYS[1]
250
+ local limit = tonumber(ARGV[1])
251
+ local cursorScoreStr = ARGV[2]
252
+ local cursorId = ARGV[3]
253
+ local updatedAfterStr = ARGV[4]
254
+
255
+ local minScore = '-inf'
256
+ if updatedAfterStr ~= '' then
257
+ minScore = '(' .. updatedAfterStr
258
+ end
259
+
260
+ local results = {}
261
+ local needed = limit + 1
262
+ local currScore = nil
263
+
264
+ if cursorScoreStr ~= '' and cursorId ~= '' then
265
+ local cursorScore = tonumber(cursorScoreStr)
266
+ local rank = redis.call('ZRANK', zsetKey, cursorId)
267
+ local startRank = nil
268
+ if rank then
269
+ startRank = rank + 1
270
+ else
271
+ local members = redis.call('ZRANGEBYSCORE', zsetKey, cursorScore, cursorScore)
272
+ for _, m in ipairs(members) do
273
+ if m > cursorId then
274
+ startRank = redis.call('ZRANK', zsetKey, m)
275
+ break
276
+ end
277
+ end
278
+ end
279
+
280
+ if startRank then
281
+ local chunk = redis.call('ZRANGE', zsetKey, startRank, startRank + needed - 1, 'WITHSCORES')
282
+ for i = 1, #chunk, 2 do
283
+ local id = chunk[i]
284
+ local s = tonumber(chunk[i + 1])
285
+ if s == cursorScore then
286
+ table.insert(results, { id, s })
287
+ if #results == needed then
288
+ break
289
+ end
290
+ else
291
+ break
292
+ end
293
+ end
294
+ end
295
+ currScore = cursorScore
296
+ else
297
+ local top = redis.call('ZREVRANGEBYSCORE', zsetKey, '+inf', minScore, 'LIMIT', 0, 1, 'WITHSCORES')
298
+ if #top > 0 then
299
+ currScore = tonumber(top[2])
300
+ local chunk = redis.call('ZRANGEBYSCORE', zsetKey, currScore, currScore, 'LIMIT', 0, needed)
301
+ for _, id in ipairs(chunk) do
302
+ table.insert(results, { id, currScore })
303
+ if #results == needed then
304
+ break
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ while #results < needed and currScore ~= nil do
311
+ local nextTop = redis.call('ZREVRANGEBYSCORE', zsetKey, '(' .. currScore, minScore, 'LIMIT', 0, 1, 'WITHSCORES')
312
+ if #nextTop == 0 then
313
+ break
314
+ end
315
+ currScore = tonumber(nextTop[2])
316
+ local countNeeded = needed - #results
317
+ local chunk = redis.call('ZRANGEBYSCORE', zsetKey, currScore, currScore, 'LIMIT', 0, countNeeded)
318
+ for _, id in ipairs(chunk) do
319
+ table.insert(results, { id, currScore })
320
+ if #results == needed then
321
+ break
322
+ end
323
+ end
324
+ end
325
+
326
+ if #results == 0 then
327
+ return '[]'
328
+ end
329
+ return cjson.encode(results)
330
+ `;
331
+ const LIST_ITEMS_SCRIPT = `
332
+ local zsetKey = KEYS[1]
333
+ local numItems = tonumber(ARGV[1])
334
+ local results = {}
335
+
336
+ for i = 1, numItems do
337
+ local metaKey = KEYS[1 + i]
338
+ local msgsKey = KEYS[1 + numItems + i]
339
+ local id = ARGV[1 + i]
340
+
341
+ local meta = redis.call('HGETALL', metaKey)
342
+ if #meta > 0 then
343
+ local count = redis.call('LLEN', msgsKey)
344
+ table.insert(results, { id, meta, count })
345
+ else
346
+ redis.call('ZREM', zsetKey, id)
347
+ table.insert(results, { id, {}, 0 })
348
+ end
349
+ end
350
+
351
+ if #results == 0 then
352
+ return '[]'
353
+ end
354
+ return cjson.encode(results)
355
+ `;
356
+ export class RedisConversationStore {
357
+ redis;
358
+ zsetKey;
359
+ slotPrefix;
360
+ ttlMs;
361
+ constructor(redis, prefix, ttlMs) {
362
+ this.redis = redis;
363
+ this.slotPrefix = formatSlotPrefix(prefix);
364
+ this.zsetKey = `${this.slotPrefix}:conversations`;
365
+ this.ttlMs = Math.ceil(ttlMs);
366
+ }
367
+ metaKey(id) {
368
+ return `${this.slotPrefix}:conv:${id}:meta`;
369
+ }
370
+ messagesKey(id) {
371
+ return `${this.slotPrefix}:conv:${id}:messages`;
372
+ }
373
+ serializeMetadata(metadata) {
374
+ if (!metadata)
375
+ return [];
376
+ const entries = [];
377
+ for (const [k, v] of Object.entries(metadata)) {
378
+ if (v !== undefined) {
379
+ entries.push(k, JSON.stringify(v));
380
+ }
381
+ }
382
+ return entries;
383
+ }
384
+ async get(id) {
385
+ const raw = await this.redis.eval(GET_SCRIPT, [this.metaKey(id), this.messagesKey(id)], []);
386
+ if (!raw)
387
+ return null;
388
+ const res = decodeEvalResult(raw);
389
+ const rawMeta = normalizeList(res?.meta);
390
+ if (rawMeta.length === 0)
391
+ return null;
392
+ const metaMap = {};
393
+ const metadata = {};
394
+ let hasMetadata = false;
395
+ for (let i = 0; i < rawMeta.length; i += 2) {
396
+ const k = String(rawMeta[i]);
397
+ const v = rawMeta[i + 1];
398
+ if (k.startsWith('meta:')) {
399
+ const field = k.slice(5);
400
+ try {
401
+ metadata[field] = typeof v === 'string' ? JSON.parse(v) : v;
402
+ }
403
+ catch {
404
+ metadata[field] = v;
405
+ }
406
+ hasMetadata = true;
407
+ }
408
+ else if (k === 'metadata' && !hasMetadata) {
409
+ // Backwards compatibility with legacy store format
410
+ try {
411
+ const parsed = typeof v === 'string' ? JSON.parse(v) : v;
412
+ if (parsed && typeof parsed === 'object') {
413
+ Object.assign(metadata, parsed);
414
+ hasMetadata = true;
415
+ }
416
+ }
417
+ catch { }
418
+ }
419
+ else {
420
+ metaMap[k] = v;
421
+ }
422
+ }
423
+ const rawMessages = normalizeList(res?.messages);
424
+ const messages = rawMessages.map((m) => typeof m === 'string' ? JSON.parse(m) : m);
425
+ return {
426
+ id, // Preserve requested id directly
427
+ messages,
428
+ version: Number(metaMap.version ?? 0),
429
+ createdAt: Number(metaMap.createdAt ?? 0),
430
+ updatedAt: Number(metaMap.updatedAt ?? 0),
431
+ ...(hasMetadata ? { metadata } : {}),
432
+ };
433
+ }
434
+ async save(conversation) {
435
+ const id = conversation.id;
436
+ const updatedAt = conversation.updatedAt ?? Date.now();
437
+ const createdAt = conversation.createdAt ?? 0;
438
+ const metaPairs = this.serializeMetadata(conversation.metadata);
439
+ const numMeta = metaPairs.length / 2;
440
+ const messagesJson = (conversation.messages ?? []).map((m) => JSON.stringify(m));
441
+ await this.redis.eval(SAVE_SCRIPT, [this.metaKey(id), this.messagesKey(id), this.zsetKey], [id, createdAt, updatedAt, this.ttlMs, numMeta, ...metaPairs, ...messagesJson]);
442
+ }
443
+ async append(id, messages, options = {}) {
444
+ const expectedVersionStr = options.expectedVersion !== undefined ? String(options.expectedVersion) : '';
445
+ const now = Date.now();
446
+ const metaPairs = this.serializeMetadata(options.metadata);
447
+ const numMeta = metaPairs.length / 2;
448
+ const messagesJson = messages.map((m) => JSON.stringify(m));
449
+ const raw = await this.redis.eval(APPEND_SCRIPT, [this.metaKey(id), this.messagesKey(id), this.zsetKey], [id, expectedVersionStr, now, this.ttlMs, numMeta, ...metaPairs, ...messagesJson]);
450
+ const res = decodeEvalResult(raw);
451
+ if (res[0] === 'CONFLICT') {
452
+ const actualVersion = Number(res[1]);
453
+ throw new ConflictError(id, options.expectedVersion ?? 0, actualVersion);
454
+ }
455
+ return { version: Number(res[1]) };
456
+ }
457
+ async updateMessage(id, message) {
458
+ const now = Date.now();
459
+ const messageJson = JSON.stringify(message);
460
+ const res = await this.redis.eval(UPDATE_MESSAGE_SCRIPT, [this.metaKey(id), this.messagesKey(id), this.zsetKey], [id, message.id, messageJson, now, this.ttlMs]);
461
+ return Number(res) === 1;
462
+ }
463
+ async removeMessage(id, messageId) {
464
+ const now = Date.now();
465
+ const res = await this.redis.eval(REMOVE_MESSAGE_SCRIPT, [this.metaKey(id), this.messagesKey(id), this.zsetKey], [id, messageId, now, this.ttlMs]);
466
+ return Number(res) === 1;
467
+ }
468
+ async delete(id) {
469
+ await this.redis.eval(DELETE_SCRIPT, [this.metaKey(id), this.messagesKey(id), this.zsetKey], [id]);
470
+ }
471
+ async list(query) {
472
+ let cursorScore = '';
473
+ let cursorId = '';
474
+ if (query.cursor) {
475
+ const colonIdx = query.cursor.indexOf(':');
476
+ if (colonIdx !== -1) {
477
+ const s = Number(query.cursor.slice(0, colonIdx));
478
+ if (!Number.isNaN(s)) {
479
+ cursorScore = String(s);
480
+ cursorId = query.cursor.slice(colonIdx + 1);
481
+ }
482
+ }
483
+ if (!cursorScore || !cursorId) {
484
+ // Unknown or invalid cursor returns empty items
485
+ return { items: [] };
486
+ }
487
+ }
488
+ const updatedAfterStr = query.updatedAfter !== undefined ? String(query.updatedAfter) : '';
489
+ const rawCandidateResults = await this.redis.eval(LIST_IDS_SCRIPT, [this.zsetKey], [query.limit, cursorScore, cursorId, updatedAfterStr]);
490
+ const candidates = normalizeList(decodeEvalResult(rawCandidateResults));
491
+ if (candidates.length === 0) {
492
+ return { items: [] };
493
+ }
494
+ const hasMore = candidates.length > query.limit;
495
+ const pageCandidates = candidates.slice(0, query.limit);
496
+ const pageIds = pageCandidates.map((c) => c[0]);
497
+ if (pageIds.length === 0) {
498
+ return { items: [] };
499
+ }
500
+ // Step 2: Fetch metadata and message counts with cluster-safe key passing
501
+ const metaKeys = pageIds.map((id) => this.metaKey(id));
502
+ const msgsKeys = pageIds.map((id) => this.messagesKey(id));
503
+ const keys = [this.zsetKey, ...metaKeys, ...msgsKeys];
504
+ const scriptArgs = [pageIds.length, ...pageIds];
505
+ const rawResults = await this.redis.eval(LIST_ITEMS_SCRIPT, keys, scriptArgs);
506
+ const results = normalizeList(decodeEvalResult(rawResults));
507
+ const items = [];
508
+ for (const [id, rawMeta, messageCount] of results) {
509
+ const metaArray = normalizeList(rawMeta);
510
+ if (metaArray.length === 0)
511
+ continue;
512
+ const metaMap = {};
513
+ const metadata = {};
514
+ let hasMetadata = false;
515
+ for (let i = 0; i < metaArray.length; i += 2) {
516
+ const k = String(metaArray[i]);
517
+ const v = metaArray[i + 1];
518
+ if (k.startsWith('meta:')) {
519
+ const field = k.slice(5);
520
+ try {
521
+ metadata[field] = typeof v === 'string' ? JSON.parse(v) : v;
522
+ }
523
+ catch {
524
+ metadata[field] = v;
525
+ }
526
+ hasMetadata = true;
527
+ }
528
+ else if (k === 'metadata' && !hasMetadata) {
529
+ try {
530
+ const parsed = typeof v === 'string' ? JSON.parse(v) : v;
531
+ if (parsed && typeof parsed === 'object') {
532
+ Object.assign(metadata, parsed);
533
+ hasMetadata = true;
534
+ }
535
+ }
536
+ catch { }
537
+ }
538
+ else {
539
+ metaMap[k] = v;
540
+ }
541
+ }
542
+ items.push({
543
+ id: String(id),
544
+ createdAt: Number(metaMap.createdAt ?? 0),
545
+ updatedAt: Number(metaMap.updatedAt ?? 0),
546
+ messageCount: Number(messageCount),
547
+ ...(hasMetadata ? { metadata } : {}),
548
+ });
549
+ }
550
+ if (hasMore && items.length > 0) {
551
+ const last = pageCandidates[pageCandidates.length - 1];
552
+ const nextCursor = `${last[1]}:${last[0]}`;
553
+ return { items, cursor: nextCursor };
554
+ }
555
+ return { items };
556
+ }
557
+ async purge(before) {
558
+ let totalPurged = 0;
559
+ const BATCH_SIZE = 100;
560
+ while (true) {
561
+ // Step 1: Query a batch of conversation IDs updated before cutoff
562
+ const rawIds = await this.redis.eval(PURGE_IDS_SCRIPT, [this.zsetKey], [before, BATCH_SIZE]);
563
+ const ids = normalizeList(decodeEvalResult(rawIds));
564
+ if (ids.length === 0) {
565
+ break;
566
+ }
567
+ // Step 2: Delete keys with all keys explicitly passed in KEYS
568
+ const metaKeys = ids.map((id) => this.metaKey(id));
569
+ const msgsKeys = ids.map((id) => this.messagesKey(id));
570
+ const keys = [this.zsetKey, ...metaKeys, ...msgsKeys];
571
+ const scriptArgs = [ids.length, ...ids];
572
+ const res = await this.redis.eval(PURGE_EXEC_SCRIPT, keys, scriptArgs);
573
+ totalPurged += Number(res);
574
+ if (ids.length < BATCH_SIZE) {
575
+ break;
576
+ }
577
+ }
578
+ return totalPurged;
579
+ }
580
+ }
581
+ //# sourceMappingURL=conversations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversations.js","sourceRoot":"","sources":["../src/conversations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { CounterStore, CounterValue } from '@chatcops/core';
2
+ import type { RedisLike } from './types.js';
3
+ export declare class RedisCounterStore implements CounterStore {
4
+ private readonly redis;
5
+ private readonly slotPrefix;
6
+ constructor(redis: RedisLike, prefix: string);
7
+ private key;
8
+ increment(key: string, by: number, ttlMs: number): Promise<CounterValue>;
9
+ get(key: string): Promise<CounterValue | null>;
10
+ }
11
+ //# sourceMappingURL=counters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counters.d.ts","sourceRoot":"","sources":["../src/counters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAwD5C,qBAAa,iBAAkB,YAAW,YAAY;IAIlD,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGjB,KAAK,EAAE,SAAS,EACjC,MAAM,EAAE,MAAM;IAKhB,OAAO,CAAC,GAAG;IAIL,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAexE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAgBrD"}