//#region src/scripts/twins.d.ts declare namespace Script { interface SyncKV { get(key: string): string | null; set(key: string, value: string, pxMs?: number): void; del(key: string): number; pexpire(key: string, ms: number): void; hget(key: string, field: string): string | null; hset(key: string, field: string, value: string): void; hdel(key: string, field: string): void; hgetall(key: string): Record; hscan(key: string, cursor: string, count: number): { cursor: string; entries: [string, string][]; }; } interface Def { lua: string; js(kv: SyncKV, keys: string[], argv: string[]): unknown; } } declare const HELPERS_LUA = "\nlocal function parseTable(raw)\n if not raw then return nil end\n local ok, value = pcall(cjson.decode, raw)\n if ok and type(value) == 'table' then return value end\n return nil\nend\nlocal function liveOwner(workersKey, sessionId, now)\n if type(sessionId) ~= 'string' then return nil end\n local raw = redis.call('HGET', workersKey, sessionId)\n local rec = parseTable(raw)\n if not rec or type(rec.expiry) ~= 'number' or rec.expiry <= now then\n return nil\n end\n return raw, rec\nend\nlocal function rewriteNs(workersKey, nsWorkersKey, ns, ensureSid, removeSid, now)\n local out = {}\n local list = parseTable(redis.call('HGET', nsWorkersKey, ns))\n if list then\n for _, sid in ipairs(list) do\n if sid ~= ensureSid and sid ~= removeSid\n and liveOwner(workersKey, sid, now) then\n out[#out + 1] = sid\n end\n end\n end\n if ensureSid then out[#out + 1] = ensureSid end\n if #out == 0 then\n redis.call('HDEL', nsWorkersKey, ns)\n else\n redis.call('HSET', nsWorkersKey, ns, cjson.encode(out))\n end\n return #out\nend\nlocal function bindEpoch(epochsKey, field)\n local rec = parseTable(redis.call('HGET', epochsKey, field))\n if rec and type(rec.epoch) == 'number' then return rec end\n return { epoch = 0 }\nend\nlocal function pruneWorkers(workersKey, bindingsKey, epochsKey, now, lease)\n local live = {}\n local all = redis.call('HGETALL', workersKey)\n for i = 1, #all, 2 do\n local rec = parseTable(all[i + 1])\n if not rec or type(rec.expiry) ~= 'number' or rec.expiry + lease < now then\n redis.call('HDEL', workersKey, all[i])\n elseif rec.expiry > now and type(rec.envs) == 'table' then\n for ns, env in pairs(rec.envs) do\n live['h:' .. tostring(rec.hostname) .. ns] = true\n live['e:' .. tostring(env)] = true\n end\n end\n end\n local bindings = redis.call('HGETALL', bindingsKey)\n for i = 1, #bindings, 2 do\n if not live[bindings[i]] then\n redis.call('HDEL', bindingsKey, bindings[i])\n end\n end\n local epochs = redis.call('HGETALL', epochsKey)\n for i = 1, #epochs, 2 do\n if not live[epochs[i]] then\n redis.call('HDEL', epochsKey, epochs[i])\n end\n end\nend\nlocal function drainBase(clientRaw, now)\n local cfg = parseTable(clientRaw)\n local deadline = cfg and cfg.drainDeadline\n if type(deadline) == 'number' then return true, math.min(now, deadline) end\n if deadline == cjson.null then return true, now end\n return false, now\nend\n"; declare const parseObj: (raw: string | null) => Record | null; declare const parseList: (raw: string | null) => unknown[] | null; declare const liveOwner: (kv: Script.SyncKV, workersKey: string, sessionId: unknown, now: number) => { raw: string; rec: Record; } | null; declare const rewriteNs: (kv: Script.SyncKV, workersKey: string, nsWorkersKey: string, ns: string, ensureSid: string | null, removeSid: string | null, now: number) => number; declare const bindEpoch: (kv: Script.SyncKV, epochsKey: string, field: string) => Record; declare const pruneWorkers: (kv: Script.SyncKV, workersKey: string, bindingsKey: string, epochsKey: string, now: number, lease: number) => void; declare const drainBase: (clientRaw: string | null, now: number) => { draining: boolean; base: number; }; //#endregion export { HELPERS_LUA, Script, bindEpoch, drainBase, liveOwner, parseList, parseObj, pruneWorkers, rewriteNs }; //# sourceMappingURL=twins.d.ts.map