@objectstack/service-cluster-redis 17.3.0 → 17.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,148 @@
1
1
  # @objectstack/service-cluster-redis
2
2
 
3
+ ## 17.4.0
4
+
5
+ ### Patch Changes
6
+
7
+ - c5d6803: Published `.js.map` files no longer embed the complete original source text (`sourcesContent`) — comments included. `sourcemap: true` was esbuild shorthand, and esbuild's own default for `sourcesContent` is `true`; nobody had decided to publish every package's full source (including `@internal`/test-only comments) to npm inside its source maps, it fell out of a default nobody had looked at. Measured before this change: 55 of 57 publishable packages shipped embedded source text, and maps were roughly half of `@objectstack/spec`'s published bytes.
8
+
9
+ `sourcesContent: false` is now set at one shared place (`scripts/tsup-drop-sources-content.mjs`, wired into every `tsup.config.ts` via tsup's `esbuildOptions` hook — most packages build through the repo-root config directly and pick this up with no config change of their own). `mappings` are untouched, so stack-trace positions still resolve correctly to the original file/line/column; only the embedded source text is gone.
10
+
11
+ `@objectstack/cli` (built with `tsc`, not `tsup`) never embedded source text to begin with — its maps' `sources` entries point at `src/**` paths that are not part of the published tarball either way. That is not a defect unique to `cli`: every `tsup`-built package's `sources` entries are `../src/**`-relative paths that are equally outside `files: ["dist", …]`, and were merely masked by the embedded content that just stopped shipping. Shipping `src/**` in `files[]` to make `sources` resolve was rejected — it would put most of the removed bytes straight back. So `cli`'s maps are left exactly as `tsc` emits them: this is now the fleet-consistent shape (accurate `mappings`, non-resolving-but-honest `sources` labels, no embedded text), not an outlier.
12
+
13
+ A new gate, `pnpm check:sourcemap-no-sources-content`, sweeps every built, non-private package's `dist/**/*.map` and fails if any of them carries a non-empty `sourcesContent` array — so a future `tsup.config.ts` that skips the shared hook, or a toolchain upgrade that changes esbuild's default back, is caught rather than silently re-publishing source text.
14
+ - Updated dependencies [fe0d9a4]
15
+ - Updated dependencies [ecd2158]
16
+ - Updated dependencies [f2b5e46]
17
+ - Updated dependencies [ed7243d]
18
+ - Updated dependencies [6ba0db4]
19
+ - Updated dependencies [625b0c3]
20
+ - Updated dependencies [233222e]
21
+ - Updated dependencies [07f40e5]
22
+ - Updated dependencies [ceb4877]
23
+ - Updated dependencies [e9fcd6b]
24
+ - Updated dependencies [90e7e6d]
25
+ - Updated dependencies [2bdabe6]
26
+ - Updated dependencies [ca326b5]
27
+ - Updated dependencies [8f404a5]
28
+ - Updated dependencies [68437d4]
29
+ - Updated dependencies [abb140c]
30
+ - Updated dependencies [8333a6c]
31
+ - Updated dependencies [3e3ecb0]
32
+ - Updated dependencies [3030369]
33
+ - Updated dependencies [d5d8d50]
34
+ - Updated dependencies [e08892d]
35
+ - Updated dependencies [ae05f2e]
36
+ - Updated dependencies [b548e43]
37
+ - Updated dependencies [c463d03]
38
+ - Updated dependencies [64bd6a3]
39
+ - Updated dependencies [13c48c2]
40
+ - Updated dependencies [132742f]
41
+ - Updated dependencies [85a2459]
42
+ - Updated dependencies [50dc214]
43
+ - Updated dependencies [e89fa92]
44
+ - Updated dependencies [e9fcd6b]
45
+ - Updated dependencies [8976ea1]
46
+ - Updated dependencies [56fe8c2]
47
+ - Updated dependencies [acabd24]
48
+ - Updated dependencies [ab50c8f]
49
+ - Updated dependencies [6491463]
50
+ - Updated dependencies [89cf4d6]
51
+ - Updated dependencies [21c5dcb]
52
+ - Updated dependencies [6d4d5d3]
53
+ - Updated dependencies [ed5d557]
54
+ - Updated dependencies [bca21f7]
55
+ - Updated dependencies [e9fcd6b]
56
+ - Updated dependencies [1a7a7c9]
57
+ - Updated dependencies [e9fcd6b]
58
+ - Updated dependencies [ef3a138]
59
+ - Updated dependencies [68d5dfd]
60
+ - Updated dependencies [3e21cf0]
61
+ - Updated dependencies [4cfc93b]
62
+ - Updated dependencies [efd6b43]
63
+ - Updated dependencies [859ded3]
64
+ - Updated dependencies [fa125f3]
65
+ - Updated dependencies [74628d9]
66
+ - Updated dependencies [a646120]
67
+ - Updated dependencies [6f1ce7d]
68
+ - Updated dependencies [7778115]
69
+ - Updated dependencies [2c753fe]
70
+ - Updated dependencies [52804cd]
71
+ - Updated dependencies [3f89967]
72
+ - Updated dependencies [53cf263]
73
+ - Updated dependencies [21aabbc]
74
+ - Updated dependencies [9c270bb]
75
+ - Updated dependencies [76c8c5a]
76
+ - Updated dependencies [a84e1ce]
77
+ - Updated dependencies [bf1054a]
78
+ - Updated dependencies [d8d2776]
79
+ - Updated dependencies [222dc0f]
80
+ - Updated dependencies [e9fcd6b]
81
+ - Updated dependencies [32c917d]
82
+ - Updated dependencies [f9a3c32]
83
+ - Updated dependencies [f502898]
84
+ - Updated dependencies [af7edfe]
85
+ - Updated dependencies [b60f48b]
86
+ - Updated dependencies [c78c918]
87
+ - Updated dependencies [cf9bda4]
88
+ - Updated dependencies [784cb92]
89
+ - Updated dependencies [7629f4d]
90
+ - Updated dependencies [51df9fd]
91
+ - Updated dependencies [a7da4de]
92
+ - Updated dependencies [de0bcdd]
93
+ - Updated dependencies [70f7d6d]
94
+ - Updated dependencies [c677cda]
95
+ - Updated dependencies [554a160]
96
+ - Updated dependencies [f7da71e]
97
+ - Updated dependencies [7f745c3]
98
+ - Updated dependencies [5eb24f8]
99
+ - Updated dependencies [2a3decc]
100
+ - Updated dependencies [cc00df2]
101
+ - Updated dependencies [f4e6adf]
102
+ - Updated dependencies [ee4a59b]
103
+ - Updated dependencies [4db3c61]
104
+ - Updated dependencies [5ca314a]
105
+ - Updated dependencies [e0af1a8]
106
+ - Updated dependencies [414c1fc]
107
+ - Updated dependencies [22c0279]
108
+ - Updated dependencies [0db2947]
109
+ - Updated dependencies [92b5d7f]
110
+ - Updated dependencies [613bfbd]
111
+ - Updated dependencies [abae16a]
112
+ - Updated dependencies [094b8fd]
113
+ - Updated dependencies [c7aca0d]
114
+ - Updated dependencies [c1d8f98]
115
+ - Updated dependencies [8e0b297]
116
+ - Updated dependencies [5f7fa1d]
117
+ - Updated dependencies [87f0ccc]
118
+ - Updated dependencies [aedbaef]
119
+ - Updated dependencies [c5d6803]
120
+ - Updated dependencies [10d05bb]
121
+ - Updated dependencies [69602e5]
122
+ - Updated dependencies [c3ce76c]
123
+ - Updated dependencies [7936b29]
124
+ - Updated dependencies [46803fa]
125
+ - Updated dependencies [c2a336c]
126
+ - Updated dependencies [9f890d3]
127
+ - Updated dependencies [0bb2318]
128
+ - Updated dependencies [f7db8f4]
129
+ - Updated dependencies [1ecee3e]
130
+ - Updated dependencies [9408b7f]
131
+ - Updated dependencies [e9fcd6b]
132
+ - Updated dependencies [9bcd9be]
133
+ - Updated dependencies [b398ad2]
134
+ - Updated dependencies [99261a7]
135
+ - Updated dependencies [81b426f]
136
+ - Updated dependencies [001af1c]
137
+ - Updated dependencies [fb77aa5]
138
+ - Updated dependencies [581d8f8]
139
+ - Updated dependencies [f81afe3]
140
+ - Updated dependencies [40a44b9]
141
+ - Updated dependencies [7a7fb03]
142
+ - Updated dependencies [8fd246d]
143
+ - @objectstack/spec@17.4.0
144
+ - @objectstack/service-cluster@17.4.0
145
+
3
146
  ## 17.3.0
4
147
 
5
148
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/objectstack/objectstack/packages/services/service-cluster-redis/dist/index.cjs","../src/index.ts","../src/client.ts","../src/pubsub.ts","../src/lock.ts","../src/kv.ts","../src/counter.ts"],"names":[],"mappings":"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","file":"/home/runner/work/objectstack/objectstack/packages/services/service-cluster-redis/dist/index.cjs","sourcesContent":[null,"// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/service-cluster-redis\n *\n * Redis driver for `@objectstack/service-cluster`. Import this package\n * once at process start to register the `'redis'` driver:\n *\n * ```ts\n * import '@objectstack/service-cluster-redis';\n * import { defineCluster } from '@objectstack/service-cluster';\n *\n * const cluster = defineCluster({\n * driver: 'redis',\n * url: 'redis://localhost:6379',\n * nodeId: 'web-1',\n * });\n * ```\n *\n * The driver also exports raw constructors so callers who already own\n * an ioredis client can compose primitives by hand.\n */\n\nimport type { Redis } from 'ioredis';\nimport {\n ComposedClusterService,\n registerClusterDriver,\n type DriverFactoryConfig,\n} from '@objectstack/service-cluster';\nimport { createRedisClient } from './client.js';\nimport { RedisPubSub } from './pubsub.js';\nimport { RedisLock } from './lock.js';\nimport { RedisKV } from './kv.js';\nimport { RedisCounter } from './counter.js';\n\n// Re-exports for advanced composition.\nexport { createRedisClient, duplicateForPubSub, type CreateRedisOptions } from './client.js';\nexport { RedisPubSub, type RedisPubSubOptions } from './pubsub.js';\nexport { RedisLock, type RedisLockOptions } from './lock.js';\nexport { RedisKV, VersionMismatchError, type RedisKVOptions } from './kv.js';\nexport { RedisCounter, type RedisCounterOptions } from './counter.js';\n\n/**\n * Driver-specific options accepted under `driverOptions` in\n * `ClusterCapabilityConfig`. All are optional — supply a `client` to\n * share a Redis pool with other services (e.g. `service-cache`).\n */\nexport interface RedisDriverOptions {\n /** Pre-built ioredis client. When provided, `url` is ignored. */\n client?: Redis;\n /** Key prefix applied to every Redis key (default: 'os:'). */\n keyPrefix?: string;\n /** Default lock TTL in ms. Overridden by `LockAcquireOptions.ttlMs`. */\n lockTtlMs?: number;\n /** Pub/sub subscriber error sink. */\n onError?: (err: unknown, channel: string) => void;\n}\n\n/**\n * Factory consumed by `defineCluster({ driver: 'redis' })`. Builds an\n * `IClusterService` backed by Redis. Owns the underlying ioredis client\n * iff it created it (i.e. when caller didn't pass `driverOptions.client`).\n */\nfunction redisDriverFactory(config: DriverFactoryConfig) {\n const driverOpts = (config.driverOptions ?? {}) as RedisDriverOptions;\n const ownsClient = !driverOpts.client;\n const client =\n driverOpts.client ??\n createRedisClient({ url: config.url });\n\n const keyPrefix = driverOpts.keyPrefix ?? 'os:';\n const ttlMs = config.lockTtlMs ?? driverOpts.lockTtlMs;\n\n const pubsub = new RedisPubSub({\n client,\n nodeId: config.nodeId,\n keyPrefix,\n onError: driverOpts.onError,\n });\n const lock = new RedisLock({\n client,\n keyPrefix,\n defaultTtlMs: ttlMs,\n nodeId: config.nodeId,\n });\n const kv = new RedisKV({ client, keyPrefix });\n const counter = new RedisCounter({ client, keyPrefix });\n\n const facade = new ComposedClusterService(\n config.nodeId,\n 'redis',\n pubsub,\n lock,\n kv,\n counter,\n );\n\n // Wrap close() so we also tear down the publisher client if we own it.\n const originalClose = facade.close.bind(facade);\n facade.close = async () => {\n await originalClose();\n if (ownsClient) {\n try { await client.quit(); } catch { /* swallow */ }\n }\n };\n\n return facade;\n}\n\n// Module-load registration — importing this package is enough.\nregisterClusterDriver('redis', redisDriverFactory);\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Redis, type RedisOptions } from 'ioredis';\n\n/**\n * Options accepted by {@link createRedisClient}.\n *\n * Either pass `url` (e.g. `redis://user:pass@host:6379/0`) or a full\n * ioredis `options` bag. The two are merged with `options` taking\n * precedence so callers can override individual fields parsed from the\n * URL.\n *\n * This factory is intended to be the single Redis-client construction\n * point across ObjectStack — `service-cluster-redis` uses it for the\n * driver, and `service-cache` will eventually share the same connection\n * pool via {@link CreateRedisOptions.existing}.\n */\nexport interface CreateRedisOptions {\n /** Connection URL. Ignored when `existing` is provided. */\n url?: string;\n /** Extra ioredis options merged on top of `url`. */\n options?: RedisOptions;\n /**\n * Bring-your-own client. When provided, this exact instance is\n * returned and `url`/`options` are ignored — useful for sharing one\n * pool across cluster + cache.\n */\n existing?: Redis;\n /**\n * If true, the returned client is created in lazyConnect mode so the\n * TCP connection happens on first command rather than at construction.\n * Default: true (matches ObjectStack's \"fail at usage, not boot\" stance).\n */\n lazyConnect?: boolean;\n}\n\n/**\n * Construct (or reuse) an ioredis client with ObjectStack defaults.\n *\n * Defaults applied when `existing` is absent:\n * - `lazyConnect: true` — don't crash boot if Redis is briefly down\n * - `maxRetriesPerRequest: 3` — bound the failure window before surfacing\n * - `enableAutoPipelining: true` — modest throughput boost for batch workloads\n *\n * @example\n * const client = createRedisClient({ url: 'redis://localhost:6379' });\n *\n * @example reuse one pool across services\n * const shared = createRedisClient({ url });\n * const clusterClient = createRedisClient({ existing: shared });\n * const cacheClient = createRedisClient({ existing: shared });\n */\nexport function createRedisClient(opts: CreateRedisOptions = {}): Redis {\n if (opts.existing) return opts.existing;\n\n const base: RedisOptions = {\n lazyConnect: opts.lazyConnect ?? true,\n maxRetriesPerRequest: 3,\n enableAutoPipelining: true,\n };\n\n if (opts.url) {\n return new Redis(opts.url, { ...base, ...opts.options });\n }\n return new Redis({ ...base, ...opts.options });\n}\n\n/**\n * Duplicate a Redis client so that pub/sub commands (which monopolize\n * the connection) don't block regular commands. Mirrors the standard\n * ioredis \"two clients\" pattern.\n */\nexport function duplicateForPubSub(client: Redis): Redis {\n return client.duplicate();\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type {\n IPubSub,\n PubSubHandler,\n PublishOptions,\n SubscribeOptions,\n Unsubscribe,\n} from '@objectstack/spec/contracts';\nimport { duplicateForPubSub } from './client.js';\n\n/**\n * Wire-format envelope sent over Redis. Adds `fromNode` and\n * `publishedAt` so subscribers see the same surface as the memory\n * driver. The user payload is nested under `p` to avoid colliding with\n * reserved keys.\n */\ninterface RedisPubSubEnvelope {\n n?: string;\n t: number;\n p: unknown;\n}\n\nexport interface RedisPubSubOptions {\n /** Already-connected client used for PUBLISH. */\n client: Redis;\n /** Optional node id surfaced as `fromNode` on every delivered message. */\n nodeId?: string;\n /** Key namespace prefix applied to every channel (default: 'os:'). */\n keyPrefix?: string;\n /** Error sink for subscriber handler exceptions. */\n onError?: (err: unknown, channel: string) => void;\n}\n\n/**\n * Redis pub/sub implementation of {@link IPubSub}.\n *\n * Uses two ioredis clients under the hood:\n * - `publisher` (caller-provided) — runs PUBLISH commands\n * - `subscriber` (auto-duplicated) — held in subscribe mode, can't run\n * regular commands per Redis protocol\n *\n * Delivery semantics match Redis pub/sub: at-most-once, fire-and-forget,\n * no persistence. For at-least-once + replay use the planned `streams`\n * adapter (separate driver).\n *\n * Channel names are prefixed with `keyPrefix` before being sent to\n * Redis, so the same Redis instance can host multiple isolated\n * ObjectStack deployments.\n */\nexport class RedisPubSub implements IPubSub {\n private readonly publisher: Redis;\n private readonly subscriber: Redis;\n private readonly nodeId?: string;\n private readonly keyPrefix: string;\n private readonly onError: (err: unknown, channel: string) => void;\n private readonly subs = new Map<string, Set<PubSubHandler<unknown>>>();\n private closed = false;\n\n constructor(opts: RedisPubSubOptions) {\n this.publisher = opts.client;\n this.subscriber = duplicateForPubSub(opts.client);\n this.nodeId = opts.nodeId;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n this.onError =\n opts.onError ??\n ((err, channel) => {\n console.error(`[RedisPubSub] handler error on \"${channel}\":`, err);\n });\n\n this.subscriber.on('message', (raw: string, data: string) => {\n this.dispatch(raw, data);\n });\n }\n\n /**\n * Durability contract (P1-5): this awaits the Redis `PUBLISH` command (so the\n * message left this node), but Redis pub/sub is **at-most-once** — there is no\n * delivery guarantee to subscribers and no replay for a node that was down or\n * slow at publish time. This is acceptable **only** for events that are pure\n * cache-invalidation hints, never the source of truth.\n *\n * In particular `metadata.changed` is such a hint: the durable record of every\n * metadata mutation is the transactional write to `sys_metadata`\n * (+ `sys_metadata_history`). A subscriber that misses the event keeps serving\n * its cached schema until its next reload and **loses no data** — it self-heals\n * on restart / reload against the DB. Do not route any state that must be\n * delivered exactly-once through this channel; use a durable outbox instead.\n */\n async publish<T = unknown>(\n channel: string,\n payload: T,\n _opts?: PublishOptions,\n ): Promise<void> {\n if (this.closed) throw new Error('RedisPubSub is closed');\n const envelope: RedisPubSubEnvelope = {\n n: this.nodeId,\n t: Date.now(),\n p: payload,\n };\n await this.publisher.publish(this.prefixed(channel), JSON.stringify(envelope));\n }\n\n subscribe<T = unknown>(\n channel: string,\n handler: PubSubHandler<T>,\n _opts?: SubscribeOptions,\n ): Unsubscribe {\n if (this.closed) throw new Error('RedisPubSub is closed');\n const prefixed = this.prefixed(channel);\n let bucket = this.subs.get(prefixed);\n if (!bucket) {\n bucket = new Set();\n this.subs.set(prefixed, bucket);\n // Fire-and-forget; if subscribe fails the next publish will\n // simply not deliver — caller can resubscribe.\n void this.subscriber.subscribe(prefixed).catch((err) => {\n this.onError(err, channel);\n });\n }\n const wrapped = handler as PubSubHandler<unknown>;\n bucket.add(wrapped);\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n const b = this.subs.get(prefixed);\n if (!b) return;\n b.delete(wrapped);\n if (b.size === 0) {\n this.subs.delete(prefixed);\n void this.subscriber.unsubscribe(prefixed).catch(() => { /* swallow */ });\n }\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.subs.clear();\n try { await this.subscriber.quit(); } catch { /* swallow */ }\n // We don't quit `publisher` — caller owns it.\n }\n\n private prefixed(channel: string): string {\n return `${this.keyPrefix}ps:${channel}`;\n }\n\n private dispatch(prefixedChannel: string, data: string): void {\n const bucket = this.subs.get(prefixedChannel);\n if (!bucket || bucket.size === 0) return;\n\n let envelope: RedisPubSubEnvelope;\n try {\n envelope = JSON.parse(data) as RedisPubSubEnvelope;\n } catch (err) {\n this.onError(err, prefixedChannel);\n return;\n }\n\n // Strip our keyPrefix so the handler sees the logical channel.\n const logical = prefixedChannel.startsWith(`${this.keyPrefix}ps:`)\n ? prefixedChannel.slice(`${this.keyPrefix}ps:`.length)\n : prefixedChannel;\n\n const snapshot = Array.from(bucket);\n for (const handler of snapshot) {\n try {\n const result = handler({\n channel: logical,\n payload: envelope.p,\n publishedAt: envelope.t,\n fromNode: envelope.n,\n });\n if (result && typeof (result as Promise<void>).then === 'function') {\n (result as Promise<void>).catch((err) =>\n this.onError(err, logical),\n );\n }\n } catch (err) {\n this.onError(err, logical);\n }\n }\n }\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type {\n ILock,\n LockAcquireOptions,\n LockHandle,\n} from '@objectstack/spec/contracts';\n\nconst DEFAULT_TTL_MS = 15_000;\nconst POLL_INTERVAL_MS = 50;\n\n/**\n * Lua script for safe release: only DEL when the value matches our\n * fencing token. Prevents a delayed release from kicking out the\n * legitimate next holder.\n */\nconst RELEASE_SCRIPT = `\nif redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n return redis.call(\"DEL\", KEYS[1])\nelse\n return 0\nend\n`;\n\n/**\n * Lua script for renew: PEXPIRE only when we still hold the lock.\n * Returns 1 on success, 0 if the lock was lost.\n */\nconst RENEW_SCRIPT = `\nif redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n return redis.call(\"PEXPIRE\", KEYS[1], ARGV[2])\nelse\n return 0\nend\n`;\n\nexport interface RedisLockOptions {\n client: Redis;\n /** Counter client for fencing-token allocation. Same Redis is fine. */\n counterClient?: Redis;\n keyPrefix?: string;\n defaultTtlMs?: number;\n /** Stable node id baked into lock values for debugging. */\n nodeId?: string;\n}\n\n/**\n * Redis-backed distributed lock with TTL fencing.\n *\n * Algorithm (single-instance Redis, NOT Redlock — adequate for\n * typical ObjectStack deployments with one Redis primary):\n *\n * acquire = SET key {nodeId}:{token} NX PX ttl\n * release = Lua: GET == expected ? DEL : 0\n * renew = Lua: GET == expected ? PEXPIRE : 0\n *\n * Fencing tokens come from a Redis counter (INCR on `{prefix}fence:{key}`)\n * so that two clients in a split-brain see strictly increasing tokens\n * downstream.\n *\n * For multi-master Redis (Sentinel failover, etc.) consider switching to\n * a Redlock variant — not implemented yet.\n */\nexport class RedisLock implements ILock {\n private readonly client: Redis;\n private readonly counterClient: Redis;\n private readonly keyPrefix: string;\n private readonly defaultTtlMs: number;\n private readonly nodeId: string;\n private closed = false;\n\n constructor(opts: RedisLockOptions) {\n this.client = opts.client;\n this.counterClient = opts.counterClient ?? opts.client;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n this.defaultTtlMs = opts.defaultTtlMs ?? DEFAULT_TTL_MS;\n this.nodeId = opts.nodeId ?? 'node';\n }\n\n async acquire(key: string, opts: LockAcquireOptions = {}): Promise<LockHandle | null> {\n if (this.closed) throw new Error('RedisLock is closed');\n const ttlMs = opts.ttlMs ?? this.defaultTtlMs;\n const waitMs = opts.waitMs ?? 0;\n const deadline = Date.now() + waitMs;\n const lockKey = this.lockKey(key);\n\n // Allocate a fresh fencing token up-front.\n const fencingToken = BigInt(\n await this.counterClient.incr(this.fenceKey(key)),\n );\n const value = `${this.nodeId}:${fencingToken}`;\n\n // First attempt — fast path.\n if (await this.trySet(lockKey, value, ttlMs)) {\n return this.makeHandle(key, lockKey, value, fencingToken, ttlMs);\n }\n if (waitMs <= 0) return null;\n\n // Polling loop: simple, correct, good enough for typical\n // contention. Future: pub/sub-driven wakeup on release.\n while (Date.now() < deadline) {\n await sleep(Math.min(POLL_INTERVAL_MS, Math.max(1, deadline - Date.now())));\n if (await this.trySet(lockKey, value, ttlMs)) {\n return this.makeHandle(key, lockKey, value, fencingToken, ttlMs);\n }\n }\n return null;\n }\n\n async withLock<T>(\n key: string,\n fn: (h: LockHandle) => Promise<T>,\n opts?: LockAcquireOptions,\n ): Promise<T | null> {\n const handle = await this.acquire(key, opts);\n if (!handle) return null;\n try {\n return await fn(handle);\n } finally {\n await handle.release();\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n private async trySet(lockKey: string, value: string, ttlMs: number): Promise<boolean> {\n // SET key value NX PX ttlMs — atomic acquire.\n const res = await this.client.set(lockKey, value, 'PX', ttlMs, 'NX');\n return res === 'OK';\n }\n\n private makeHandle(\n logicalKey: string,\n lockKey: string,\n value: string,\n fencingToken: bigint,\n ttlMs: number,\n ): LockHandle {\n const self = this;\n let released = false;\n let currentTtl = ttlMs;\n // Local expiry timer — mirrors memory driver so `isHeld()` flips\n // on TTL without a Redis roundtrip. Not authoritative (clocks may\n // drift), but matches contract test expectations.\n let timer: NodeJS.Timeout | undefined = setTimeout(() => {\n released = true;\n }, ttlMs);\n\n return {\n key: logicalKey,\n fencingToken,\n isHeld(): boolean {\n return !released;\n },\n async renew(extendMs?: number): Promise<void> {\n if (released) {\n throw new Error(`Lock \"${logicalKey}\" already released`);\n }\n const next = extendMs ?? currentTtl;\n const result = await self.client.eval(\n RENEW_SCRIPT,\n 1,\n lockKey,\n value,\n String(next),\n );\n if (result !== 1) {\n released = true;\n if (timer) { clearTimeout(timer); timer = undefined; }\n throw new Error(\n `Lock \"${logicalKey}\" no longer held (fence=${fencingToken})`,\n );\n }\n currentTtl = next;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => { released = true; }, next);\n },\n async release(): Promise<void> {\n if (released) return;\n released = true;\n if (timer) { clearTimeout(timer); timer = undefined; }\n try {\n await self.client.eval(RELEASE_SCRIPT, 1, lockKey, value);\n } catch {\n /* swallow — release is best-effort */\n }\n },\n };\n }\n\n private lockKey(key: string): string {\n return `${this.keyPrefix}lock:${key}`;\n }\n\n private fenceKey(key: string): string {\n return `${this.keyPrefix}fence:${key}`;\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type { IKV, KVEntry, KVSetOptions } from '@objectstack/spec/contracts';\n\n/**\n * Stored payload shape: `{v: <value>, ver: <bigint as string>}`.\n * Versions are stored as strings because Redis values are bytes and\n * bigints can exceed JSON-safe-integer range.\n */\ninterface StoredKV {\n v: unknown;\n ver: string;\n}\n\nexport class VersionMismatchError extends Error {\n constructor(\n public readonly key: string,\n public readonly expected: bigint,\n public readonly actual: bigint,\n ) {\n super(\n `KV version mismatch on \"${key}\": expected v${expected}, found v${actual}`,\n );\n this.name = 'VersionMismatchError';\n }\n}\n\nexport interface RedisKVOptions {\n client: Redis;\n keyPrefix?: string;\n}\n\n/**\n * Redis-backed coordination KV with optimistic concurrency via WATCH/MULTI.\n *\n * Each `set()` performs:\n * 1. WATCH key\n * 2. GET key → read current version\n * 3. compare to ifVersion (if provided)\n * 4. MULTI / SET / [PEXPIRE] / EXEC\n *\n * If a competing writer modifies the key between WATCH and EXEC the\n * transaction aborts and we throw `VersionMismatchError`, matching\n * memory driver semantics.\n *\n * **Not** a cache — uses small JSON envelopes and per-key versioning.\n * Use service-cache for high-throughput caching.\n */\nexport class RedisKV implements IKV {\n private readonly client: Redis;\n private readonly keyPrefix: string;\n private closed = false;\n\n constructor(opts: RedisKVOptions) {\n this.client = opts.client;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n }\n\n async get<T = unknown>(key: string): Promise<KVEntry<T> | undefined> {\n const raw = await this.client.get(this.kvKey(key));\n if (raw === null) return undefined;\n const parsed = this.parse(raw);\n if (!parsed) return undefined;\n const pttl = await this.client.pttl(this.kvKey(key));\n const expiresAt = pttl > 0 ? Date.now() + pttl : undefined;\n return {\n key,\n value: parsed.v as T,\n version: BigInt(parsed.ver),\n expiresAt,\n };\n }\n\n async set<T = unknown>(\n key: string,\n value: T,\n opts: KVSetOptions = {},\n ): Promise<KVEntry<T>> {\n if (this.closed) throw new Error('RedisKV is closed');\n const physical = this.kvKey(key);\n const ttlMs = opts.ttl && opts.ttl > 0 ? opts.ttl * 1000 : undefined;\n\n // Optimistic-concurrency loop — Redis WATCH aborts the MULTI on\n // any intervening write.\n while (true) {\n await this.client.watch(physical);\n const raw = await this.client.get(physical);\n const existing = raw ? this.parse(raw) : undefined;\n const existingVersion = existing ? BigInt(existing.ver) : 0n;\n\n if (opts.ifVersion !== undefined && opts.ifVersion !== existingVersion) {\n await this.client.unwatch();\n throw new VersionMismatchError(key, opts.ifVersion, existingVersion);\n }\n\n const newVersion = existingVersion + 1n;\n const payload: StoredKV = { v: value, ver: newVersion.toString() };\n const encoded = JSON.stringify(payload);\n\n const multi = this.client.multi();\n if (ttlMs) {\n multi.set(physical, encoded, 'PX', ttlMs);\n } else {\n multi.set(physical, encoded);\n }\n const result = await multi.exec();\n // exec() returns null when WATCH detected a concurrent change.\n if (result === null) continue;\n\n return {\n key,\n value,\n version: newVersion,\n expiresAt: ttlMs ? Date.now() + ttlMs : undefined,\n };\n }\n }\n\n async delete(key: string, opts: { ifVersion?: bigint } = {}): Promise<boolean> {\n if (this.closed) throw new Error('RedisKV is closed');\n const physical = this.kvKey(key);\n\n if (opts.ifVersion === undefined) {\n const removed = await this.client.del(physical);\n return removed > 0;\n }\n\n while (true) {\n await this.client.watch(physical);\n const raw = await this.client.get(physical);\n if (!raw) {\n await this.client.unwatch();\n return false;\n }\n const parsed = this.parse(raw);\n if (!parsed) {\n await this.client.unwatch();\n return false;\n }\n const currentVersion = BigInt(parsed.ver);\n if (opts.ifVersion !== currentVersion) {\n await this.client.unwatch();\n throw new VersionMismatchError(key, opts.ifVersion, currentVersion);\n }\n const multi = this.client.multi();\n multi.del(physical);\n const result = await multi.exec();\n if (result === null) continue;\n return (result[0]?.[1] as number) > 0;\n }\n }\n\n async cas<T = unknown>(\n key: string,\n expectedVersion: bigint,\n next: T,\n opts: Omit<KVSetOptions, 'ifVersion'> = {},\n ): Promise<KVEntry<T> | undefined> {\n try {\n return await this.set(key, next, { ...opts, ifVersion: expectedVersion });\n } catch (err) {\n if (err instanceof VersionMismatchError) return undefined;\n throw err;\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n private kvKey(key: string): string {\n return `${this.keyPrefix}kv:${key}`;\n }\n\n private parse(raw: string): StoredKV | undefined {\n try {\n const obj = JSON.parse(raw) as StoredKV;\n if (typeof obj.ver !== 'string') return undefined;\n return obj;\n } catch {\n return undefined;\n }\n }\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type { ICounter, CounterIncrOptions } from '@objectstack/spec/contracts';\n\nexport interface RedisCounterOptions {\n client: Redis;\n keyPrefix?: string;\n}\n\n/**\n * Redis-backed monotonic counter using INCRBY. Each counter key lives at\n * `{prefix}ctr:{key}` so the same Redis instance can host multiple\n * tenants without collision.\n *\n * Values are stored as ASCII decimals (Redis convention). We surface\n * them as `bigint` to match the contract — INCRBY accepts up to a\n * signed 64-bit range, well beyond Number.MAX_SAFE_INTEGER.\n */\nexport class RedisCounter implements ICounter {\n private readonly client: Redis;\n private readonly keyPrefix: string;\n private closed = false;\n\n constructor(opts: RedisCounterOptions) {\n this.client = opts.client;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n }\n\n async incr(key: string, opts: CounterIncrOptions = {}): Promise<bigint> {\n if (this.closed) throw new Error('RedisCounter is closed');\n const by = opts.by ?? 1;\n const next = await this.client.incrby(this.ctrKey(key), by);\n return BigInt(next);\n }\n\n async peek(key: string): Promise<bigint> {\n const raw = await this.client.get(this.ctrKey(key));\n if (raw === null) return 0n;\n try {\n return BigInt(raw);\n } catch {\n return 0n;\n }\n }\n\n async reset(key: string, value: bigint = 0n): Promise<void> {\n if (this.closed) throw new Error('RedisCounter is closed');\n if (value === 0n) {\n await this.client.del(this.ctrKey(key));\n return;\n }\n await this.client.set(this.ctrKey(key), value.toString());\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n private ctrKey(key: string): string {\n return `${this.keyPrefix}ctr:${key}`;\n }\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/objectstack/objectstack/packages/services/service-cluster-redis/dist/index.cjs","../src/index.ts","../src/client.ts","../src/pubsub.ts","../src/lock.ts","../src/kv.ts","../src/counter.ts"],"names":[],"mappings":"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","file":"/home/runner/work/objectstack/objectstack/packages/services/service-cluster-redis/dist/index.cjs"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/pubsub.ts","../src/lock.ts","../src/kv.ts","../src/counter.ts"],"sourcesContent":["// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/service-cluster-redis\n *\n * Redis driver for `@objectstack/service-cluster`. Import this package\n * once at process start to register the `'redis'` driver:\n *\n * ```ts\n * import '@objectstack/service-cluster-redis';\n * import { defineCluster } from '@objectstack/service-cluster';\n *\n * const cluster = defineCluster({\n * driver: 'redis',\n * url: 'redis://localhost:6379',\n * nodeId: 'web-1',\n * });\n * ```\n *\n * The driver also exports raw constructors so callers who already own\n * an ioredis client can compose primitives by hand.\n */\n\nimport type { Redis } from 'ioredis';\nimport {\n ComposedClusterService,\n registerClusterDriver,\n type DriverFactoryConfig,\n} from '@objectstack/service-cluster';\nimport { createRedisClient } from './client.js';\nimport { RedisPubSub } from './pubsub.js';\nimport { RedisLock } from './lock.js';\nimport { RedisKV } from './kv.js';\nimport { RedisCounter } from './counter.js';\n\n// Re-exports for advanced composition.\nexport { createRedisClient, duplicateForPubSub, type CreateRedisOptions } from './client.js';\nexport { RedisPubSub, type RedisPubSubOptions } from './pubsub.js';\nexport { RedisLock, type RedisLockOptions } from './lock.js';\nexport { RedisKV, VersionMismatchError, type RedisKVOptions } from './kv.js';\nexport { RedisCounter, type RedisCounterOptions } from './counter.js';\n\n/**\n * Driver-specific options accepted under `driverOptions` in\n * `ClusterCapabilityConfig`. All are optional — supply a `client` to\n * share a Redis pool with other services (e.g. `service-cache`).\n */\nexport interface RedisDriverOptions {\n /** Pre-built ioredis client. When provided, `url` is ignored. */\n client?: Redis;\n /** Key prefix applied to every Redis key (default: 'os:'). */\n keyPrefix?: string;\n /** Default lock TTL in ms. Overridden by `LockAcquireOptions.ttlMs`. */\n lockTtlMs?: number;\n /** Pub/sub subscriber error sink. */\n onError?: (err: unknown, channel: string) => void;\n}\n\n/**\n * Factory consumed by `defineCluster({ driver: 'redis' })`. Builds an\n * `IClusterService` backed by Redis. Owns the underlying ioredis client\n * iff it created it (i.e. when caller didn't pass `driverOptions.client`).\n */\nfunction redisDriverFactory(config: DriverFactoryConfig) {\n const driverOpts = (config.driverOptions ?? {}) as RedisDriverOptions;\n const ownsClient = !driverOpts.client;\n const client =\n driverOpts.client ??\n createRedisClient({ url: config.url });\n\n const keyPrefix = driverOpts.keyPrefix ?? 'os:';\n const ttlMs = config.lockTtlMs ?? driverOpts.lockTtlMs;\n\n const pubsub = new RedisPubSub({\n client,\n nodeId: config.nodeId,\n keyPrefix,\n onError: driverOpts.onError,\n });\n const lock = new RedisLock({\n client,\n keyPrefix,\n defaultTtlMs: ttlMs,\n nodeId: config.nodeId,\n });\n const kv = new RedisKV({ client, keyPrefix });\n const counter = new RedisCounter({ client, keyPrefix });\n\n const facade = new ComposedClusterService(\n config.nodeId,\n 'redis',\n pubsub,\n lock,\n kv,\n counter,\n );\n\n // Wrap close() so we also tear down the publisher client if we own it.\n const originalClose = facade.close.bind(facade);\n facade.close = async () => {\n await originalClose();\n if (ownsClient) {\n try { await client.quit(); } catch { /* swallow */ }\n }\n };\n\n return facade;\n}\n\n// Module-load registration — importing this package is enough.\nregisterClusterDriver('redis', redisDriverFactory);\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Redis, type RedisOptions } from 'ioredis';\n\n/**\n * Options accepted by {@link createRedisClient}.\n *\n * Either pass `url` (e.g. `redis://user:pass@host:6379/0`) or a full\n * ioredis `options` bag. The two are merged with `options` taking\n * precedence so callers can override individual fields parsed from the\n * URL.\n *\n * This factory is intended to be the single Redis-client construction\n * point across ObjectStack — `service-cluster-redis` uses it for the\n * driver, and `service-cache` will eventually share the same connection\n * pool via {@link CreateRedisOptions.existing}.\n */\nexport interface CreateRedisOptions {\n /** Connection URL. Ignored when `existing` is provided. */\n url?: string;\n /** Extra ioredis options merged on top of `url`. */\n options?: RedisOptions;\n /**\n * Bring-your-own client. When provided, this exact instance is\n * returned and `url`/`options` are ignored — useful for sharing one\n * pool across cluster + cache.\n */\n existing?: Redis;\n /**\n * If true, the returned client is created in lazyConnect mode so the\n * TCP connection happens on first command rather than at construction.\n * Default: true (matches ObjectStack's \"fail at usage, not boot\" stance).\n */\n lazyConnect?: boolean;\n}\n\n/**\n * Construct (or reuse) an ioredis client with ObjectStack defaults.\n *\n * Defaults applied when `existing` is absent:\n * - `lazyConnect: true` — don't crash boot if Redis is briefly down\n * - `maxRetriesPerRequest: 3` — bound the failure window before surfacing\n * - `enableAutoPipelining: true` — modest throughput boost for batch workloads\n *\n * @example\n * const client = createRedisClient({ url: 'redis://localhost:6379' });\n *\n * @example reuse one pool across services\n * const shared = createRedisClient({ url });\n * const clusterClient = createRedisClient({ existing: shared });\n * const cacheClient = createRedisClient({ existing: shared });\n */\nexport function createRedisClient(opts: CreateRedisOptions = {}): Redis {\n if (opts.existing) return opts.existing;\n\n const base: RedisOptions = {\n lazyConnect: opts.lazyConnect ?? true,\n maxRetriesPerRequest: 3,\n enableAutoPipelining: true,\n };\n\n if (opts.url) {\n return new Redis(opts.url, { ...base, ...opts.options });\n }\n return new Redis({ ...base, ...opts.options });\n}\n\n/**\n * Duplicate a Redis client so that pub/sub commands (which monopolize\n * the connection) don't block regular commands. Mirrors the standard\n * ioredis \"two clients\" pattern.\n */\nexport function duplicateForPubSub(client: Redis): Redis {\n return client.duplicate();\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type {\n IPubSub,\n PubSubHandler,\n PublishOptions,\n SubscribeOptions,\n Unsubscribe,\n} from '@objectstack/spec/contracts';\nimport { duplicateForPubSub } from './client.js';\n\n/**\n * Wire-format envelope sent over Redis. Adds `fromNode` and\n * `publishedAt` so subscribers see the same surface as the memory\n * driver. The user payload is nested under `p` to avoid colliding with\n * reserved keys.\n */\ninterface RedisPubSubEnvelope {\n n?: string;\n t: number;\n p: unknown;\n}\n\nexport interface RedisPubSubOptions {\n /** Already-connected client used for PUBLISH. */\n client: Redis;\n /** Optional node id surfaced as `fromNode` on every delivered message. */\n nodeId?: string;\n /** Key namespace prefix applied to every channel (default: 'os:'). */\n keyPrefix?: string;\n /** Error sink for subscriber handler exceptions. */\n onError?: (err: unknown, channel: string) => void;\n}\n\n/**\n * Redis pub/sub implementation of {@link IPubSub}.\n *\n * Uses two ioredis clients under the hood:\n * - `publisher` (caller-provided) — runs PUBLISH commands\n * - `subscriber` (auto-duplicated) — held in subscribe mode, can't run\n * regular commands per Redis protocol\n *\n * Delivery semantics match Redis pub/sub: at-most-once, fire-and-forget,\n * no persistence. For at-least-once + replay use the planned `streams`\n * adapter (separate driver).\n *\n * Channel names are prefixed with `keyPrefix` before being sent to\n * Redis, so the same Redis instance can host multiple isolated\n * ObjectStack deployments.\n */\nexport class RedisPubSub implements IPubSub {\n private readonly publisher: Redis;\n private readonly subscriber: Redis;\n private readonly nodeId?: string;\n private readonly keyPrefix: string;\n private readonly onError: (err: unknown, channel: string) => void;\n private readonly subs = new Map<string, Set<PubSubHandler<unknown>>>();\n private closed = false;\n\n constructor(opts: RedisPubSubOptions) {\n this.publisher = opts.client;\n this.subscriber = duplicateForPubSub(opts.client);\n this.nodeId = opts.nodeId;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n this.onError =\n opts.onError ??\n ((err, channel) => {\n console.error(`[RedisPubSub] handler error on \"${channel}\":`, err);\n });\n\n this.subscriber.on('message', (raw: string, data: string) => {\n this.dispatch(raw, data);\n });\n }\n\n /**\n * Durability contract (P1-5): this awaits the Redis `PUBLISH` command (so the\n * message left this node), but Redis pub/sub is **at-most-once** — there is no\n * delivery guarantee to subscribers and no replay for a node that was down or\n * slow at publish time. This is acceptable **only** for events that are pure\n * cache-invalidation hints, never the source of truth.\n *\n * In particular `metadata.changed` is such a hint: the durable record of every\n * metadata mutation is the transactional write to `sys_metadata`\n * (+ `sys_metadata_history`). A subscriber that misses the event keeps serving\n * its cached schema until its next reload and **loses no data** — it self-heals\n * on restart / reload against the DB. Do not route any state that must be\n * delivered exactly-once through this channel; use a durable outbox instead.\n */\n async publish<T = unknown>(\n channel: string,\n payload: T,\n _opts?: PublishOptions,\n ): Promise<void> {\n if (this.closed) throw new Error('RedisPubSub is closed');\n const envelope: RedisPubSubEnvelope = {\n n: this.nodeId,\n t: Date.now(),\n p: payload,\n };\n await this.publisher.publish(this.prefixed(channel), JSON.stringify(envelope));\n }\n\n subscribe<T = unknown>(\n channel: string,\n handler: PubSubHandler<T>,\n _opts?: SubscribeOptions,\n ): Unsubscribe {\n if (this.closed) throw new Error('RedisPubSub is closed');\n const prefixed = this.prefixed(channel);\n let bucket = this.subs.get(prefixed);\n if (!bucket) {\n bucket = new Set();\n this.subs.set(prefixed, bucket);\n // Fire-and-forget; if subscribe fails the next publish will\n // simply not deliver — caller can resubscribe.\n void this.subscriber.subscribe(prefixed).catch((err) => {\n this.onError(err, channel);\n });\n }\n const wrapped = handler as PubSubHandler<unknown>;\n bucket.add(wrapped);\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n const b = this.subs.get(prefixed);\n if (!b) return;\n b.delete(wrapped);\n if (b.size === 0) {\n this.subs.delete(prefixed);\n void this.subscriber.unsubscribe(prefixed).catch(() => { /* swallow */ });\n }\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.subs.clear();\n try { await this.subscriber.quit(); } catch { /* swallow */ }\n // We don't quit `publisher` — caller owns it.\n }\n\n private prefixed(channel: string): string {\n return `${this.keyPrefix}ps:${channel}`;\n }\n\n private dispatch(prefixedChannel: string, data: string): void {\n const bucket = this.subs.get(prefixedChannel);\n if (!bucket || bucket.size === 0) return;\n\n let envelope: RedisPubSubEnvelope;\n try {\n envelope = JSON.parse(data) as RedisPubSubEnvelope;\n } catch (err) {\n this.onError(err, prefixedChannel);\n return;\n }\n\n // Strip our keyPrefix so the handler sees the logical channel.\n const logical = prefixedChannel.startsWith(`${this.keyPrefix}ps:`)\n ? prefixedChannel.slice(`${this.keyPrefix}ps:`.length)\n : prefixedChannel;\n\n const snapshot = Array.from(bucket);\n for (const handler of snapshot) {\n try {\n const result = handler({\n channel: logical,\n payload: envelope.p,\n publishedAt: envelope.t,\n fromNode: envelope.n,\n });\n if (result && typeof (result as Promise<void>).then === 'function') {\n (result as Promise<void>).catch((err) =>\n this.onError(err, logical),\n );\n }\n } catch (err) {\n this.onError(err, logical);\n }\n }\n }\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type {\n ILock,\n LockAcquireOptions,\n LockHandle,\n} from '@objectstack/spec/contracts';\n\nconst DEFAULT_TTL_MS = 15_000;\nconst POLL_INTERVAL_MS = 50;\n\n/**\n * Lua script for safe release: only DEL when the value matches our\n * fencing token. Prevents a delayed release from kicking out the\n * legitimate next holder.\n */\nconst RELEASE_SCRIPT = `\nif redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n return redis.call(\"DEL\", KEYS[1])\nelse\n return 0\nend\n`;\n\n/**\n * Lua script for renew: PEXPIRE only when we still hold the lock.\n * Returns 1 on success, 0 if the lock was lost.\n */\nconst RENEW_SCRIPT = `\nif redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n return redis.call(\"PEXPIRE\", KEYS[1], ARGV[2])\nelse\n return 0\nend\n`;\n\nexport interface RedisLockOptions {\n client: Redis;\n /** Counter client for fencing-token allocation. Same Redis is fine. */\n counterClient?: Redis;\n keyPrefix?: string;\n defaultTtlMs?: number;\n /** Stable node id baked into lock values for debugging. */\n nodeId?: string;\n}\n\n/**\n * Redis-backed distributed lock with TTL fencing.\n *\n * Algorithm (single-instance Redis, NOT Redlock — adequate for\n * typical ObjectStack deployments with one Redis primary):\n *\n * acquire = SET key {nodeId}:{token} NX PX ttl\n * release = Lua: GET == expected ? DEL : 0\n * renew = Lua: GET == expected ? PEXPIRE : 0\n *\n * Fencing tokens come from a Redis counter (INCR on `{prefix}fence:{key}`)\n * so that two clients in a split-brain see strictly increasing tokens\n * downstream.\n *\n * For multi-master Redis (Sentinel failover, etc.) consider switching to\n * a Redlock variant — not implemented yet.\n */\nexport class RedisLock implements ILock {\n private readonly client: Redis;\n private readonly counterClient: Redis;\n private readonly keyPrefix: string;\n private readonly defaultTtlMs: number;\n private readonly nodeId: string;\n private closed = false;\n\n constructor(opts: RedisLockOptions) {\n this.client = opts.client;\n this.counterClient = opts.counterClient ?? opts.client;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n this.defaultTtlMs = opts.defaultTtlMs ?? DEFAULT_TTL_MS;\n this.nodeId = opts.nodeId ?? 'node';\n }\n\n async acquire(key: string, opts: LockAcquireOptions = {}): Promise<LockHandle | null> {\n if (this.closed) throw new Error('RedisLock is closed');\n const ttlMs = opts.ttlMs ?? this.defaultTtlMs;\n const waitMs = opts.waitMs ?? 0;\n const deadline = Date.now() + waitMs;\n const lockKey = this.lockKey(key);\n\n // Allocate a fresh fencing token up-front.\n const fencingToken = BigInt(\n await this.counterClient.incr(this.fenceKey(key)),\n );\n const value = `${this.nodeId}:${fencingToken}`;\n\n // First attempt — fast path.\n if (await this.trySet(lockKey, value, ttlMs)) {\n return this.makeHandle(key, lockKey, value, fencingToken, ttlMs);\n }\n if (waitMs <= 0) return null;\n\n // Polling loop: simple, correct, good enough for typical\n // contention. Future: pub/sub-driven wakeup on release.\n while (Date.now() < deadline) {\n await sleep(Math.min(POLL_INTERVAL_MS, Math.max(1, deadline - Date.now())));\n if (await this.trySet(lockKey, value, ttlMs)) {\n return this.makeHandle(key, lockKey, value, fencingToken, ttlMs);\n }\n }\n return null;\n }\n\n async withLock<T>(\n key: string,\n fn: (h: LockHandle) => Promise<T>,\n opts?: LockAcquireOptions,\n ): Promise<T | null> {\n const handle = await this.acquire(key, opts);\n if (!handle) return null;\n try {\n return await fn(handle);\n } finally {\n await handle.release();\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n private async trySet(lockKey: string, value: string, ttlMs: number): Promise<boolean> {\n // SET key value NX PX ttlMs — atomic acquire.\n const res = await this.client.set(lockKey, value, 'PX', ttlMs, 'NX');\n return res === 'OK';\n }\n\n private makeHandle(\n logicalKey: string,\n lockKey: string,\n value: string,\n fencingToken: bigint,\n ttlMs: number,\n ): LockHandle {\n const self = this;\n let released = false;\n let currentTtl = ttlMs;\n // Local expiry timer — mirrors memory driver so `isHeld()` flips\n // on TTL without a Redis roundtrip. Not authoritative (clocks may\n // drift), but matches contract test expectations.\n let timer: NodeJS.Timeout | undefined = setTimeout(() => {\n released = true;\n }, ttlMs);\n\n return {\n key: logicalKey,\n fencingToken,\n isHeld(): boolean {\n return !released;\n },\n async renew(extendMs?: number): Promise<void> {\n if (released) {\n throw new Error(`Lock \"${logicalKey}\" already released`);\n }\n const next = extendMs ?? currentTtl;\n const result = await self.client.eval(\n RENEW_SCRIPT,\n 1,\n lockKey,\n value,\n String(next),\n );\n if (result !== 1) {\n released = true;\n if (timer) { clearTimeout(timer); timer = undefined; }\n throw new Error(\n `Lock \"${logicalKey}\" no longer held (fence=${fencingToken})`,\n );\n }\n currentTtl = next;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => { released = true; }, next);\n },\n async release(): Promise<void> {\n if (released) return;\n released = true;\n if (timer) { clearTimeout(timer); timer = undefined; }\n try {\n await self.client.eval(RELEASE_SCRIPT, 1, lockKey, value);\n } catch {\n /* swallow — release is best-effort */\n }\n },\n };\n }\n\n private lockKey(key: string): string {\n return `${this.keyPrefix}lock:${key}`;\n }\n\n private fenceKey(key: string): string {\n return `${this.keyPrefix}fence:${key}`;\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type { IKV, KVEntry, KVSetOptions } from '@objectstack/spec/contracts';\n\n/**\n * Stored payload shape: `{v: <value>, ver: <bigint as string>}`.\n * Versions are stored as strings because Redis values are bytes and\n * bigints can exceed JSON-safe-integer range.\n */\ninterface StoredKV {\n v: unknown;\n ver: string;\n}\n\nexport class VersionMismatchError extends Error {\n constructor(\n public readonly key: string,\n public readonly expected: bigint,\n public readonly actual: bigint,\n ) {\n super(\n `KV version mismatch on \"${key}\": expected v${expected}, found v${actual}`,\n );\n this.name = 'VersionMismatchError';\n }\n}\n\nexport interface RedisKVOptions {\n client: Redis;\n keyPrefix?: string;\n}\n\n/**\n * Redis-backed coordination KV with optimistic concurrency via WATCH/MULTI.\n *\n * Each `set()` performs:\n * 1. WATCH key\n * 2. GET key → read current version\n * 3. compare to ifVersion (if provided)\n * 4. MULTI / SET / [PEXPIRE] / EXEC\n *\n * If a competing writer modifies the key between WATCH and EXEC the\n * transaction aborts and we throw `VersionMismatchError`, matching\n * memory driver semantics.\n *\n * **Not** a cache — uses small JSON envelopes and per-key versioning.\n * Use service-cache for high-throughput caching.\n */\nexport class RedisKV implements IKV {\n private readonly client: Redis;\n private readonly keyPrefix: string;\n private closed = false;\n\n constructor(opts: RedisKVOptions) {\n this.client = opts.client;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n }\n\n async get<T = unknown>(key: string): Promise<KVEntry<T> | undefined> {\n const raw = await this.client.get(this.kvKey(key));\n if (raw === null) return undefined;\n const parsed = this.parse(raw);\n if (!parsed) return undefined;\n const pttl = await this.client.pttl(this.kvKey(key));\n const expiresAt = pttl > 0 ? Date.now() + pttl : undefined;\n return {\n key,\n value: parsed.v as T,\n version: BigInt(parsed.ver),\n expiresAt,\n };\n }\n\n async set<T = unknown>(\n key: string,\n value: T,\n opts: KVSetOptions = {},\n ): Promise<KVEntry<T>> {\n if (this.closed) throw new Error('RedisKV is closed');\n const physical = this.kvKey(key);\n const ttlMs = opts.ttl && opts.ttl > 0 ? opts.ttl * 1000 : undefined;\n\n // Optimistic-concurrency loop — Redis WATCH aborts the MULTI on\n // any intervening write.\n while (true) {\n await this.client.watch(physical);\n const raw = await this.client.get(physical);\n const existing = raw ? this.parse(raw) : undefined;\n const existingVersion = existing ? BigInt(existing.ver) : 0n;\n\n if (opts.ifVersion !== undefined && opts.ifVersion !== existingVersion) {\n await this.client.unwatch();\n throw new VersionMismatchError(key, opts.ifVersion, existingVersion);\n }\n\n const newVersion = existingVersion + 1n;\n const payload: StoredKV = { v: value, ver: newVersion.toString() };\n const encoded = JSON.stringify(payload);\n\n const multi = this.client.multi();\n if (ttlMs) {\n multi.set(physical, encoded, 'PX', ttlMs);\n } else {\n multi.set(physical, encoded);\n }\n const result = await multi.exec();\n // exec() returns null when WATCH detected a concurrent change.\n if (result === null) continue;\n\n return {\n key,\n value,\n version: newVersion,\n expiresAt: ttlMs ? Date.now() + ttlMs : undefined,\n };\n }\n }\n\n async delete(key: string, opts: { ifVersion?: bigint } = {}): Promise<boolean> {\n if (this.closed) throw new Error('RedisKV is closed');\n const physical = this.kvKey(key);\n\n if (opts.ifVersion === undefined) {\n const removed = await this.client.del(physical);\n return removed > 0;\n }\n\n while (true) {\n await this.client.watch(physical);\n const raw = await this.client.get(physical);\n if (!raw) {\n await this.client.unwatch();\n return false;\n }\n const parsed = this.parse(raw);\n if (!parsed) {\n await this.client.unwatch();\n return false;\n }\n const currentVersion = BigInt(parsed.ver);\n if (opts.ifVersion !== currentVersion) {\n await this.client.unwatch();\n throw new VersionMismatchError(key, opts.ifVersion, currentVersion);\n }\n const multi = this.client.multi();\n multi.del(physical);\n const result = await multi.exec();\n if (result === null) continue;\n return (result[0]?.[1] as number) > 0;\n }\n }\n\n async cas<T = unknown>(\n key: string,\n expectedVersion: bigint,\n next: T,\n opts: Omit<KVSetOptions, 'ifVersion'> = {},\n ): Promise<KVEntry<T> | undefined> {\n try {\n return await this.set(key, next, { ...opts, ifVersion: expectedVersion });\n } catch (err) {\n if (err instanceof VersionMismatchError) return undefined;\n throw err;\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n private kvKey(key: string): string {\n return `${this.keyPrefix}kv:${key}`;\n }\n\n private parse(raw: string): StoredKV | undefined {\n try {\n const obj = JSON.parse(raw) as StoredKV;\n if (typeof obj.ver !== 'string') return undefined;\n return obj;\n } catch {\n return undefined;\n }\n }\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Redis } from 'ioredis';\nimport type { ICounter, CounterIncrOptions } from '@objectstack/spec/contracts';\n\nexport interface RedisCounterOptions {\n client: Redis;\n keyPrefix?: string;\n}\n\n/**\n * Redis-backed monotonic counter using INCRBY. Each counter key lives at\n * `{prefix}ctr:{key}` so the same Redis instance can host multiple\n * tenants without collision.\n *\n * Values are stored as ASCII decimals (Redis convention). We surface\n * them as `bigint` to match the contract — INCRBY accepts up to a\n * signed 64-bit range, well beyond Number.MAX_SAFE_INTEGER.\n */\nexport class RedisCounter implements ICounter {\n private readonly client: Redis;\n private readonly keyPrefix: string;\n private closed = false;\n\n constructor(opts: RedisCounterOptions) {\n this.client = opts.client;\n this.keyPrefix = opts.keyPrefix ?? 'os:';\n }\n\n async incr(key: string, opts: CounterIncrOptions = {}): Promise<bigint> {\n if (this.closed) throw new Error('RedisCounter is closed');\n const by = opts.by ?? 1;\n const next = await this.client.incrby(this.ctrKey(key), by);\n return BigInt(next);\n }\n\n async peek(key: string): Promise<bigint> {\n const raw = await this.client.get(this.ctrKey(key));\n if (raw === null) return 0n;\n try {\n return BigInt(raw);\n } catch {\n return 0n;\n }\n }\n\n async reset(key: string, value: bigint = 0n): Promise<void> {\n if (this.closed) throw new Error('RedisCounter is closed');\n if (value === 0n) {\n await this.client.del(this.ctrKey(key));\n return;\n }\n await this.client.set(this.ctrKey(key), value.toString());\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n\n private ctrKey(key: string): string {\n return `${this.keyPrefix}ctr:${key}`;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/pubsub.ts","../src/lock.ts","../src/kv.ts","../src/counter.ts"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/service-cluster-redis",
3
- "version": "17.3.0",
3
+ "version": "17.4.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Redis cluster driver for ObjectStack — implements IPubSub/ILock/IKV/ICounter against Redis using ioredis.",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "ioredis": "^6.0.0",
23
- "@objectstack/service-cluster": "17.3.0",
24
- "@objectstack/spec": "17.3.0"
23
+ "@objectstack/service-cluster": "17.4.0",
24
+ "@objectstack/spec": "17.4.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^26.2.0",