UNPKG

@hotmeshio/hotmesh

Version:

Permanent-Memory Workflows & AI Agents

191 lines (190 loc) 7.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IORedisStoreService = void 0; const key_1 = require("../../../../modules/key"); const enums_1 = require("../../../../modules/enums"); const _base_1 = require("./_base"); class IORedisStoreService extends _base_1.RedisStoreBase { constructor(storeClient) { super(storeClient); this.commands = { get: 'get', set: 'set', setnx: 'setnx', del: 'del', expire: 'expire', hset: 'hset', hscan: 'hscan', hsetnx: 'hsetnx', hincrby: 'hincrby', hdel: 'hdel', hget: 'hget', hmget: 'hmget', hgetall: 'hgetall', hincrbyfloat: 'hincrbyfloat', zrank: 'zrank', zrange: 'zrange', zrangebyscore_withscores: 'zrangebyscore', zrangebyscore: 'zrangebyscore', zrem: 'zrem', zadd: 'zadd', lmove: 'lmove', lpop: 'lpop', lrange: 'lrange', rename: 'rename', rpush: 'rpush', scan: 'scan', xack: 'xack', xdel: 'xdel', }; } /** * When in cluster mode, the transact wrapper only * sends commands to the same node/shard if they share a key. * All other commands are sent simultaneouslyusing Promise.all * and are then collated. this is effectiely a wrapper for * `multi` but is closer to `pipeline` in terms of usage when * promises are used. */ transact() { const my = this; if (enums_1.HMSH_IS_CLUSTER) { const commands = []; const addCommand = (command, args) => { commands.push({ command, args }); return multiInstance; }; const multiInstance = { sendCommand(command) { return my.storeClient.sendCommand(command); }, async exec() { if (commands.length === 0) return []; const sameKey = commands.every((cmd) => { return cmd.args[0] === commands[0].args[0]; }); if (sameKey) { const multi = my.storeClient.multi(); commands.forEach((cmd) => multi[cmd.command](...cmd.args)); const results = await multi.exec(); return results.map((item) => item); } else { return Promise.all(commands.map((cmd) => my.storeClient[cmd.command](...cmd.args))); } }, xadd(key, id, fields, message) { return addCommand('xadd', [key, id, fields, message]); }, xack(key, group, id) { return addCommand('xack', [key, group, id]); }, xdel(key, id) { return addCommand('xdel', [key, id]); }, xlen(key) { return addCommand('xlen', [key]); }, xpending(key, group, start, end, count, consumer) { return addCommand('xpending', [ key, group, start, end, count, consumer, ]); }, xclaim(key, group, consumer, minIdleTime, id, ...args) { return addCommand('xclaim', [ key, group, consumer, minIdleTime, id, ...args, ]); }, del(key) { return addCommand('del', [key]); }, expire: function (key, seconds) { return addCommand('expire', [key, seconds]); }, hdel(key, itemId) { return addCommand('hdel', [key, itemId]); }, hget(key, itemId) { return addCommand('hget', [key, itemId]); }, hgetall(key) { return addCommand('hgetall', [key]); }, hincrbyfloat(key, itemId, value) { return addCommand('hincrbyfloat', [key, itemId, value]); }, hmget(key, itemIds) { return addCommand('hmget', [key, itemIds]); }, hset(key, values) { return addCommand('hset', [key, values]); }, lrange(key, start, end) { return addCommand('lrange', [key, start, end]); }, rpush(key, value) { return addCommand('rpush', [key, value]); }, zadd(...args) { return addCommand('zadd', args); }, xgroup(command, key, groupName, id, mkStream) { return addCommand('xgroup', [command, key, groupName, id, mkStream]); }, }; return multiInstance; } return this.storeClient.multi(); } async exec(...args) { try { const response = await this.storeClient.call.apply(this.storeClient, args); if (typeof response === 'string') { return response; } else if (Array.isArray(response)) { if (Array.isArray(response[0])) { return response; } return response; } return response; } catch (error) { // Connection closed during test cleanup - log and return empty response if (error?.message?.includes('Connection is closed')) { return []; } // Re-throw unexpected errors throw error; } } async setnxex(key, value, expireSeconds) { const status = await this.storeClient[this.commands.set](key, value, 'NX', 'EX', expireSeconds.toString()); return this.isSuccessful(status); } hGetAllResult(result) { //ioredis response signature is [null, {}] or [null, null] return result[1]; } async addTaskQueues(keys) { const multi = this.storeClient.multi(); const zsetKey = this.mintKey(key_1.KeyType.WORK_ITEMS, { appId: this.appId }); for (const key of keys) { multi.zadd(zsetKey, 'NX', Date.now(), key); } await multi.exec(); } } exports.IORedisStoreService = IORedisStoreService;