@absolutejs/sync-bus-redis 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -5,6 +5,8 @@ Redis pub/sub `ClusterBus` for
5
5
  [`@absolutejs/sync-bus-pg`](../bus-pg) — same `ClusterBus` contract,
6
6
  different transport.
7
7
 
8
+ **Docs:** [absolutejs.com/documentation/cluster-bus-overview#redis-adapter](https://absolutejs.com/documentation/cluster-bus-overview#redis-adapter)
9
+
8
10
  ## When to use Redis vs Postgres
9
11
 
10
12
  | Concern | `sync-bus-redis` | `sync-bus-pg` |
package/dist/index.js CHANGED
@@ -1,4 +1,19 @@
1
1
  // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
2
17
  // src/index.ts
3
18
  var createRedisClusterBus = (options) => {
4
19
  const channel = options.channel ?? "absolutejs_sync_cluster";
@@ -44,5 +59,5 @@ export {
44
59
  createRedisClusterBus
45
60
  };
46
61
 
47
- //# debugId=0C163B79C3CB22BF64756E2164756E21
62
+ //# debugId=4645E21AE8A8C0AC64756E2164756E21
48
63
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "/**\n * @absolutejs/sync-bus-redis — Redis pub/sub `ClusterBus` for\n * `@absolutejs/sync`. Cross-instance fan-out via PUBLISH/SUBSCRIBE.\n *\n * **Why Redis (vs the `sync-bus-pg` sibling).**\n *\n * - **No payload cap.** Postgres `NOTIFY` is capped at 8000 bytes,\n * forcing `sync-bus-pg` into a spill-table dance for large batches.\n * Redis PUBLISH has no equivalent limit — JSON straight through.\n * - **Lower latency at fan-out.** Redis pub/sub is in-memory; PG\n * `LISTEN/NOTIFY` rides the WAL replication path. For multi-shard\n * fan-out (10+ subscribers), Redis is typically faster.\n * - **Better geo-replication story.** Redis Cluster / Redis\n * Enterprise / managed Redis (ElastiCache, Memorystore, Upstash)\n * all geo-replicate natively. Postgres logical replication is\n * possible but heavier ops.\n *\n * **Why NOT Redis (when to use `sync-bus-pg` instead).**\n *\n * - **At-most-once delivery.** Redis pub/sub does NOT durably store\n * messages. A subscriber that's disconnected when a message fires\n * misses it. If you need a durable cluster bus for replay across\n * shard reboot, use `sync-bus-pg` (which has the spill table) and\n * pair with `engine.exportChangeLog()` / `importChangeLog()` for\n * post-reboot resume.\n * - **Already have Postgres in your stack.** Adding Redis just for\n * the cluster bus is a new dependency to operate.\n *\n * **Client compatibility.**\n *\n * The adapter takes a narrow interface (`publisher.publish(channel,\n * message)` and `subscriber.subscribe(channel, listener)`) so it works\n * with any 2026-era Redis client:\n *\n * - `ioredis`: `const redis = new Redis(url); const sub = redis.duplicate();`\n * - `node-redis` v4+: `const client = createClient({ url }); const sub = client.duplicate();`\n *\n * Each pub/sub-using consumer needs TWO connections — one for\n * publishing (your existing client), one for subscribing (a duplicate\n * dedicated to the subscription, because Redis prohibits other\n * commands on a subscribed connection). Pass both to\n * `createRedisClusterBus({ publisher, subscriber })`.\n *\n * See `README.md` for `ioredis` and `node-redis` adapter snippets.\n */\n\nimport type { ClusterBus, ClusterMessage } from '@absolutejs/sync/engine';\n\n/**\n * Minimal Redis publisher contract. Both `ioredis` and `node-redis` v4\n * structurally satisfy this (`publish(channel, message)` is the\n * canonical signature; both return a Promise that resolves to the\n * number of subscribers that received the message).\n */\nexport type RedisPublisher = {\n\tpublish: (channel: string, message: string) => Promise<number | unknown>;\n};\n\n/**\n * Minimal Redis subscriber contract. The shape diverges between\n * ioredis (EventEmitter-based) and node-redis (callback-based);\n * `RedisSubscriber` is the lowest-common-denominator:\n *\n * - `subscribe(channel, listener)` registers `listener` for messages\n * on `channel` AND returns an unsubscribe function. The listener\n * receives the raw message string.\n *\n * The README shows how to wrap ioredis (where you'd call\n * `subscriber.on('message', handler)` once and route by channel) and\n * node-redis (where `subscribe(channel, listener)` is the SDK call\n * directly).\n */\nexport type RedisSubscriber = {\n\tsubscribe: (\n\t\tchannel: string,\n\t\tlistener: (message: string) => void\n\t) => Promise<() => Promise<void>>;\n};\n\nexport type CreateRedisClusterBusOptions = {\n\t/** The Redis client used for `publish()` calls. */\n\tpublisher: RedisPublisher;\n\t/** The Redis subscriber. MUST be a dedicated connection (a\n\t * `duplicate()` of your main client) — Redis forbids other\n\t * commands on a subscribed connection. */\n\tsubscriber: RedisSubscriber;\n\t/**\n\t * Channel name. Defaults to `'absolutejs_sync_cluster'`. Two\n\t * engines on the same Redis can scope themselves to different\n\t * channels by overriding this.\n\t */\n\tchannel?: string;\n\t/**\n\t * Called when message parsing / delivery fails. Defaults to\n\t * `console.warn`. Note that Redis pub/sub doesn't surface delivery\n\t * failures on the publisher side — `publish()` resolves to the\n\t * count of subscribers that received the message (or 0); a 0 count\n\t * does NOT fire onError (Redis treats \"no subscribers\" as success).\n\t */\n\tonError?: (error: unknown) => void;\n};\n\n/**\n * Cumulative metrics since `createRedisClusterBus()`. Same shape\n * style as `sync-bus-pg`'s — minus the spill-table fields (Redis\n * has no equivalent).\n */\nexport type RedisClusterBusMetrics = {\n\tpublished: number;\n\treceived: number;\n\tpublishErrors: number;\n\tsubscribeErrors: number;\n\t/**\n\t * Cumulative count of subscribers reached on the publisher side.\n\t * Returned by Redis's PUBLISH. Use it as a rough \"is the cluster\n\t * still wired up\" signal — a drop to 0 when you expect peers means\n\t * subscribers disconnected (replication lag, network partition).\n\t */\n\ttotalSubscribersReached: number;\n};\n\nexport type RedisClusterBus = ClusterBus & {\n\tmetrics: () => RedisClusterBusMetrics;\n};\n\nexport const createRedisClusterBus = (\n\toptions: CreateRedisClusterBusOptions\n): RedisClusterBus => {\n\tconst channel = options.channel ?? 'absolutejs_sync_cluster';\n\tconst onError =\n\t\toptions.onError ?? ((error) => console.warn('[sync-bus-redis]', error));\n\n\tconst counters: RedisClusterBusMetrics = {\n\t\tpublishErrors: 0,\n\t\tpublished: 0,\n\t\treceived: 0,\n\t\tsubscribeErrors: 0,\n\t\ttotalSubscribersReached: 0\n\t};\n\n\treturn {\n\t\tmetrics: () => ({ ...counters }),\n\t\tpublish: async (message: ClusterMessage): Promise<void> => {\n\t\t\ttry {\n\t\t\t\tconst serialized = JSON.stringify(message);\n\t\t\t\tconst result = await options.publisher.publish(\n\t\t\t\t\tchannel,\n\t\t\t\t\tserialized\n\t\t\t\t);\n\t\t\t\tif (typeof result === 'number') {\n\t\t\t\t\tcounters.totalSubscribersReached += result;\n\t\t\t\t}\n\t\t\t\tcounters.published += 1;\n\t\t\t} catch (error) {\n\t\t\t\tcounters.publishErrors += 1;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tsubscribe: async (\n\t\t\tonMessage: (message: ClusterMessage) => void\n\t\t): Promise<() => Promise<void>> => {\n\t\t\tconst listener = (raw: string): void => {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw) as ClusterMessage;\n\t\t\t\t\tcounters.received += 1;\n\t\t\t\t\tonMessage(parsed);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcounters.subscribeErrors += 1;\n\t\t\t\t\tonError(error);\n\t\t\t\t}\n\t\t\t};\n\t\t\treturn options.subscriber.subscribe(channel, listener);\n\t\t}\n\t};\n};\n"
6
6
  ],
7
- "mappings": ";;AA6HO,IAAM,wBAAwB,CACpC,YACqB;AAAA,EACrB,MAAM,UAAU,QAAQ,WAAW;AAAA,EACnC,MAAM,UACL,QAAQ,YAAY,CAAC,UAAU,QAAQ,KAAK,oBAAoB,KAAK;AAAA,EAEtE,MAAM,WAAmC;AAAA,IACxC,eAAe;AAAA,IACf,WAAW;AAAA,IACX,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,EAC1B;AAAA,EAEA,OAAO;AAAA,IACN,SAAS,OAAO,KAAK,SAAS;AAAA,IAC9B,SAAS,OAAO,YAA2C;AAAA,MAC1D,IAAI;AAAA,QACH,MAAM,aAAa,KAAK,UAAU,OAAO;AAAA,QACzC,MAAM,SAAS,MAAM,QAAQ,UAAU,QACtC,SACA,UACD;AAAA,QACA,IAAI,OAAO,WAAW,UAAU;AAAA,UAC/B,SAAS,2BAA2B;AAAA,QACrC;AAAA,QACA,SAAS,aAAa;AAAA,QACrB,OAAO,OAAO;AAAA,QACf,SAAS,iBAAiB;AAAA,QAC1B,MAAM;AAAA;AAAA;AAAA,IAGR,WAAW,OACV,cACkC;AAAA,MAClC,MAAM,WAAW,CAAC,QAAsB;AAAA,QACvC,IAAI;AAAA,UACH,MAAM,SAAS,KAAK,MAAM,GAAG;AAAA,UAC7B,SAAS,YAAY;AAAA,UACrB,UAAU,MAAM;AAAA,UACf,OAAO,OAAO;AAAA,UACf,SAAS,mBAAmB;AAAA,UAC5B,QAAQ,KAAK;AAAA;AAAA;AAAA,MAGf,OAAO,QAAQ,WAAW,UAAU,SAAS,QAAQ;AAAA;AAAA,EAEvD;AAAA;",
8
- "debugId": "0C163B79C3CB22BF64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;AA6HO,IAAM,wBAAwB,CACpC,YACqB;AAAA,EACrB,MAAM,UAAU,QAAQ,WAAW;AAAA,EACnC,MAAM,UACL,QAAQ,YAAY,CAAC,UAAU,QAAQ,KAAK,oBAAoB,KAAK;AAAA,EAEtE,MAAM,WAAmC;AAAA,IACxC,eAAe;AAAA,IACf,WAAW;AAAA,IACX,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,EAC1B;AAAA,EAEA,OAAO;AAAA,IACN,SAAS,OAAO,KAAK,SAAS;AAAA,IAC9B,SAAS,OAAO,YAA2C;AAAA,MAC1D,IAAI;AAAA,QACH,MAAM,aAAa,KAAK,UAAU,OAAO;AAAA,QACzC,MAAM,SAAS,MAAM,QAAQ,UAAU,QACtC,SACA,UACD;AAAA,QACA,IAAI,OAAO,WAAW,UAAU;AAAA,UAC/B,SAAS,2BAA2B;AAAA,QACrC;AAAA,QACA,SAAS,aAAa;AAAA,QACrB,OAAO,OAAO;AAAA,QACf,SAAS,iBAAiB;AAAA,QAC1B,MAAM;AAAA;AAAA;AAAA,IAGR,WAAW,OACV,cACkC;AAAA,MAClC,MAAM,WAAW,CAAC,QAAsB;AAAA,QACvC,IAAI;AAAA,UACH,MAAM,SAAS,KAAK,MAAM,GAAG;AAAA,UAC7B,SAAS,YAAY;AAAA,UACrB,UAAU,MAAM;AAAA,UACf,OAAO,OAAO;AAAA,UACf,SAAS,mBAAmB;AAAA,UAC5B,QAAQ,KAAK;AAAA;AAAA;AAAA,MAGf,OAAO,QAAQ,WAAW,UAAU,SAAS,QAAQ;AAAA;AAAA,EAEvD;AAAA;",
8
+ "debugId": "4645E21AE8A8C0AC64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -0,0 +1,3 @@
1
+ import type { CreateRedisClusterBusOptions } from './index';
2
+ export declare const manifest: import("@absolutejs/manifest").PackageManifest<CreateRedisClusterBusOptions, never>;
3
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAM5D,eAAO,MAAM,QAAQ,qFAmEnB,CAAC"}