@vibesdotdev/integrations-redis 0.0.0-stage → 1.0.0-rc.1

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.
Files changed (67) hide show
  1. package/LICENSE +126 -0
  2. package/dist/client.d.ts +10 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +12 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/client.node.d.ts +7 -0
  7. package/dist/client.node.d.ts.map +1 -0
  8. package/dist/client.node.js +8 -0
  9. package/dist/client.node.js.map +1 -0
  10. package/dist/config.d.ts +141 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +39 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/connections.d.ts +56 -0
  15. package/dist/connections.d.ts.map +1 -0
  16. package/dist/connections.js +166 -0
  17. package/dist/connections.js.map +1 -0
  18. package/dist/index.d.ts +13 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +13 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/instrumented.d.ts +8 -0
  23. package/dist/instrumented.d.ts.map +1 -0
  24. package/dist/instrumented.js +41 -0
  25. package/dist/instrumented.js.map +1 -0
  26. package/dist/manager.d.ts +79 -0
  27. package/dist/manager.d.ts.map +1 -0
  28. package/dist/manager.js +321 -0
  29. package/dist/manager.js.map +1 -0
  30. package/dist/redis.consumer.plugin.d.ts +10 -0
  31. package/dist/redis.consumer.plugin.d.ts.map +1 -0
  32. package/dist/redis.consumer.plugin.js +30 -0
  33. package/dist/redis.consumer.plugin.js.map +1 -0
  34. package/dist/redis.plugin.d.ts +3 -0
  35. package/dist/redis.plugin.d.ts.map +1 -0
  36. package/dist/redis.plugin.js +12 -0
  37. package/dist/redis.plugin.js.map +1 -0
  38. package/dist/scheduler-lock.d.ts +20 -0
  39. package/dist/scheduler-lock.d.ts.map +1 -0
  40. package/dist/scheduler-lock.js +43 -0
  41. package/dist/scheduler-lock.js.map +1 -0
  42. package/dist/schemas/connection.d.ts +10 -0
  43. package/dist/schemas/connection.d.ts.map +1 -0
  44. package/dist/schemas/connection.js +8 -0
  45. package/dist/schemas/connection.js.map +1 -0
  46. package/dist/schemas/lock.d.ts +10 -0
  47. package/dist/schemas/lock.d.ts.map +1 -0
  48. package/dist/schemas/lock.js +4 -0
  49. package/dist/schemas/lock.js.map +1 -0
  50. package/dist/schemas/settings.d.ts +46 -0
  51. package/dist/schemas/settings.d.ts.map +1 -0
  52. package/dist/schemas/settings.js +23 -0
  53. package/dist/schemas/settings.js.map +1 -0
  54. package/dist/telemetry-ioredis.impl.d.ts +4 -0
  55. package/dist/telemetry-ioredis.impl.d.ts.map +1 -0
  56. package/dist/telemetry-ioredis.impl.js +6 -0
  57. package/dist/telemetry-ioredis.impl.js.map +1 -0
  58. package/dist/telemetry-redis.impl.d.ts +4 -0
  59. package/dist/telemetry-redis.impl.d.ts.map +1 -0
  60. package/dist/telemetry-redis.impl.js +6 -0
  61. package/dist/telemetry-redis.impl.js.map +1 -0
  62. package/dist/telemetry.d.ts +34 -0
  63. package/dist/telemetry.d.ts.map +1 -0
  64. package/dist/telemetry.js +29 -0
  65. package/dist/telemetry.js.map +1 -0
  66. package/package.json +101 -4
  67. package/README.md +0 -3
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @vibesdotdev/integrations-redis — the Redis connection registry and
3
+ * instrumented client (moved from `@vibesdotdev/logging/observability/redis`)
4
+ * and the Workers scheduler lock (moved from `@vibesdotdev/workers`), RC09.
5
+ */
6
+ export { RedisConnectionManager, redisManagerFor, getRedisConnection, disposeRedisConnections, setupRedisShutdownHandlers, REDIS_URL, redisPurposeUrlKey, resolveRedisUrl } from "./manager.js";
7
+ export { RedisConnectionPurpose, RedisConnections, redisConnectionsFor, getCacheConnection, getSessionsConnection, getWorkersConnection, getPubSubConnection, getGPUQueueConnection, getModelRegistryConnection } from "./connections.js";
8
+ export { instrumentRedisClient } from "./instrumented.js";
9
+ export { RedisSchedulerLock } from "./scheduler-lock.js";
10
+ export { RedisSettingsSchema, REDIS_SETTINGS_MANIFEST_ID, redisSettingsManifest, redisSettingsDescriptor } from "./config.js";
11
+ export { redisPlugin } from "./redis.plugin.js";
12
+ export { RedisClient } from "./client.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,SAAS,EACT,kBAAkB,EAClB,eAAe,EAEf,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAE1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAA2B,MAAM,qBAAqB,CAAC;AAClF,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,EAEvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Instrument the vendor dispatch boundary. Command overloads, callbacks and
3
+ * synchronous multi/pipeline builders remain implemented by ioredis itself.
4
+ */
5
+ import type { Redis } from 'ioredis';
6
+ import { type RuntimeRef } from '@vibesdotdev/kernel';
7
+ export declare function instrumentRedisClient(client: Redis, _runtime?: RuntimeRef): Redis;
8
+ //# sourceMappingURL=instrumented.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumented.d.ts","sourceRoot":"","sources":["../src/instrumented.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAA4B,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGhF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,UAAU,GAAG,KAAK,CAoCjF"}
@@ -0,0 +1,41 @@
1
+ import { valueFreeFailure, settle } from '@vibesdotdev/kernel';
2
+ import { SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';
3
+ export function instrumentRedisClient(client, _runtime) {
4
+ return new Proxy(client, {
5
+ get(target, prop) {
6
+ if (prop === 'sendCommand') {
7
+ return (...args) => {
8
+ const [command] = args;
9
+ return trace.getTracer('redis').startActiveSpan('redis.command', {
10
+ kind: SpanKind.CLIENT,
11
+ attributes: { 'db.system': 'redis', component: 'ioredis' }
12
+ }, (span) => {
13
+ try {
14
+ const result = target.sendCommand(...args);
15
+ void settle(() => command.promise).then((outcome) => {
16
+ if (outcome.ok) {
17
+ span.setStatus({ code: SpanStatusCode.OK });
18
+ }
19
+ else {
20
+ span.recordException(new Error('Redis command failed', { cause: valueFreeFailure(outcome.cause) }));
21
+ span.setStatus({ code: SpanStatusCode.ERROR, message: 'Redis command failed' });
22
+ }
23
+ span.end();
24
+ });
25
+ return result;
26
+ }
27
+ catch (error) {
28
+ span.setStatus({ code: SpanStatusCode.ERROR, message: 'Redis command failed' });
29
+ span.end();
30
+ throw error;
31
+ }
32
+ });
33
+ };
34
+ }
35
+ // SAFETY: Proxy property reads must preserve all vendor properties,
36
+ // including symbols. The key assertion changes no value or call contract.
37
+ return target[prop];
38
+ }
39
+ });
40
+ }
41
+ //# sourceMappingURL=instrumented.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumented.js","sourceRoot":"","sources":["../src/instrumented.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAmB,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAErE,MAAM,UAAU,qBAAqB,CAAC,MAAa,EAAE,QAAqB;IACzE,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE;QACxB,GAAG,CAAC,MAAM,EAAE,IAAI;YACf,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,IAAsC,EAAE,EAAE;oBACpD,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;oBACvB,OAAO,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,eAAe,EAAE;wBAChE,IAAI,EAAE,QAAQ,CAAC,MAAM;wBACrB,UAAU,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE;qBAC1D,EAAE,CAAC,IAAI,EAAE,EAAE;wBACX,IAAI,CAAC;4BACJ,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;4BAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gCACnD,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;oCAChB,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC;gCAC7C,CAAC;qCAAM,CAAC;oCACP,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;oCACpG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;gCACjF,CAAC;gCACD,IAAI,CAAC,GAAG,EAAE,CAAC;4BACZ,CAAC,CAAC,CAAC;4BACH,OAAO,MAAM,CAAC;wBACf,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BAChB,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;4BAChF,IAAI,CAAC,GAAG,EAAE,CAAC;4BACX,MAAM,KAAK,CAAC;wBACb,CAAC;oBACF,CAAC,CAAC,CAAC;gBACJ,CAAC,CAAC;YACH,CAAC;YAED,oEAAoE;YACpE,0EAA0E;YAC1E,OAAO,MAAM,CAAC,IAAmB,CAAC,CAAC;QACpC,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,79 @@
1
+ import type IORedis from 'ioredis';
2
+ import type { RedisOptions } from 'ioredis';
3
+ import { type RuntimeLifecycle, type RuntimeRef } from '@vibesdotdev/kernel';
4
+ import type { RedisClient } from './client.ts';
5
+ export declare function isDeclaredBuildHost(runtime: Pick<RuntimeRef, 'scope'>): boolean;
6
+ /** The base Redis URL credential; a purpose may set its own `REDIS_<PURPOSE>_URL`. */
7
+ export declare const REDIS_URL = "REDIS_URL";
8
+ /** The credential key naming `purpose`'s own Redis URL (`REDIS_CACHE_URL`, …). */
9
+ export declare function redisPurposeUrlKey(purpose: string): string;
10
+ /**
11
+ * The Redis URL on `runtime`: `purpose`'s own credential when given and set,
12
+ * else the base `REDIS_URL` credential (the declared chain). A Redis URL
13
+ * carries its password, so both are credentials, never environment reads. No
14
+ * URL at all is `UNAVAILABLE redis-url-not-set`, never a guessed localhost.
15
+ */
16
+ export declare function resolveRedisUrl(runtime: Pick<RuntimeRef, 'resolveCredential'>, purpose?: string): Promise<string>;
17
+ /**
18
+ * Centralized Redis connection manager for proper cleanup
19
+ */
20
+ export declare class RedisConnectionManager {
21
+ private connections;
22
+ private closeAllPromise;
23
+ private runtime?;
24
+ private readonly createClient;
25
+ constructor(runtimeOrCreateClient?: RuntimeRef | ((url: string, options: RedisOptions) => IORedis), createClient?: (url: string, options: RedisOptions) => IORedis);
26
+ createBuildClient(): IORedis;
27
+ private log;
28
+ private logDebug;
29
+ private logInfo;
30
+ private logWarn;
31
+ /**
32
+ * Create a new Redis connection with cleanup tracking. The caller supplies
33
+ * the URL (a resolved credential: `resolveRedisUrl`) and the runtime whose
34
+ * declared scope decides whether this is a build host.
35
+ */
36
+ createConnection(runtime: RuntimeRef, url: string, options?: RedisOptions): IORedis;
37
+ /**
38
+ * Gracefully close all tracked connections
39
+ */
40
+ closeAllConnections(): Promise<void>;
41
+ /**
42
+ * Get count of active connections
43
+ */
44
+ getConnectionCount(): number;
45
+ /**
46
+ * Wait for a connection's own `ready` event, bounded by the caller's
47
+ * runtime lifecycle (RC07): the wait rejects `TIMEOUT wait-timeout` at the
48
+ * deadline, `CANCELLED wait-aborted` when the runtime is disposed, or with
49
+ * the connection's `error`.
50
+ */
51
+ waitForConnection(redis: IORedis, lifecycle: Pick<RuntimeLifecycle, 'wait'>, timeoutMs?: number): Promise<void>;
52
+ /**
53
+ * Check if a connection is healthy
54
+ */
55
+ isConnectionHealthy(redis: IORedis): boolean;
56
+ /**
57
+ * Force disconnect all connections (emergency cleanup)
58
+ */
59
+ forceDisconnectAll(): void;
60
+ private removeConnection;
61
+ }
62
+ /** What identifies the runtime that owns a set of Redis connections. */
63
+ export type RedisOwnerRuntime = RuntimeRef;
64
+ export declare function redisClientFor(runtime: RedisOwnerRuntime): RedisClient;
65
+ export declare function redisManagerFor(runtime: RedisOwnerRuntime): RedisConnectionManager;
66
+ export declare function disposeRedisConnections(runtime: RedisOwnerRuntime): Promise<void>;
67
+ /**
68
+ * @deprecated Process-global shutdown handlers were removed from this reusable
69
+ * package. Compose `redisPlugin`: the runtime's disposal closes that
70
+ * runtime's connections (`disposeRedisConnections(runtime)`).
71
+ */
72
+ export declare function setupRedisShutdownHandlers(): never;
73
+ /**
74
+ * A Redis connection on `runtime`, tracked by the manager `runtime` owns: the URL is the
75
+ * `REDIS_URL` credential and the retry and ready-check settings are the
76
+ * `integrations.redis` manifest; `options` wins per field.
77
+ */
78
+ export declare function getRedisConnection(runtime: RuntimeRef, options?: RedisOptions): Promise<IORedis>;
79
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAwD,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAInI,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,OAAO,CAE/E;AAaD,sFAAsF;AACtF,eAAO,MAAM,SAAS,cAAc,CAAC;AAErC,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,EAC9C,OAAO,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAajB;AAED;;GAEG;AACH,qBAAa,sBAAsB;IAClC,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkD;gBAG9E,qBAAqB,CAAC,EACnB,UAAU,GACV,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,EACpD,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO;IAU/D,iBAAiB,IAAI,OAAO;IAyB5B,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,QAAQ;IAGhB,OAAO,CAAC,OAAO;IAGf,OAAO,CAAC,OAAO;IAIf;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO;IA4DnF;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgDpC;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAM5B;;;;;OAKG;IACH,iBAAiB,CAChB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,EACzC,SAAS,SAAmD,GAC1D,OAAO,CAAC,IAAI,CAAC;IA+BhB;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAI5C;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAkB1B,OAAO,CAAC,gBAAgB;CAIxB;AAED,wEAAwE;AACxE,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE3C,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,WAAW,CAItE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,sBAAsB,CAElF;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,KAAK,CAIlD;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAStG"}
@@ -0,0 +1,321 @@
1
+ import { CapabilityError, valueFreeFailure, settle, settleNow } from '@vibesdotdev/kernel';
2
+ import { getLogger } from '@vibesdotdev/logging';
3
+ import { getVibesClient, tryGetVibesClient } from '@vibesdotdev/kernel/client';
4
+ import { RedisSettingsSchema, redisSettingsManifest } from "./config.js";
5
+ import { RedisCredentialSchema } from "./schemas/connection.js";
6
+ export function isDeclaredBuildHost(runtime) {
7
+ return runtime.scope.lifecycle === 'finite' && runtime.scope.qualifiers.building === true;
8
+ }
9
+ async function resolveOptionalSecret(runtime, key) {
10
+ const result = await runtime.resolveCredential({ source: 'secret', key });
11
+ if (result.ok) {
12
+ const parsed = RedisCredentialSchema.safeParse(result.value);
13
+ if (parsed.success)
14
+ return parsed.data;
15
+ throw new CapabilityError('Invalid Redis credential', 'INVALID_INPUT', { reason: 'redis-credential-invalid' });
16
+ }
17
+ if (result.error.code === 'NOT_FOUND' && result.error.reason === 'credential-not-set')
18
+ return null;
19
+ throw result.error;
20
+ }
21
+ /** The base Redis URL credential; a purpose may set its own `REDIS_<PURPOSE>_URL`. */
22
+ export const REDIS_URL = 'REDIS_URL';
23
+ /** The credential key naming `purpose`'s own Redis URL (`REDIS_CACHE_URL`, …). */
24
+ export function redisPurposeUrlKey(purpose) {
25
+ return `REDIS_${purpose.toUpperCase()}_URL`;
26
+ }
27
+ /**
28
+ * The Redis URL on `runtime`: `purpose`'s own credential when given and set,
29
+ * else the base `REDIS_URL` credential (the declared chain). A Redis URL
30
+ * carries its password, so both are credentials, never environment reads. No
31
+ * URL at all is `UNAVAILABLE redis-url-not-set`, never a guessed localhost.
32
+ */
33
+ export async function resolveRedisUrl(runtime, purpose) {
34
+ if (purpose) {
35
+ const own = await resolveOptionalSecret(runtime, redisPurposeUrlKey(purpose));
36
+ if (own)
37
+ return own;
38
+ }
39
+ const base = await resolveOptionalSecret(runtime, REDIS_URL);
40
+ if (base)
41
+ return base;
42
+ const keys = purpose ? `${redisPurposeUrlKey(purpose)} or ${REDIS_URL}` : REDIS_URL;
43
+ throw new CapabilityError(`No Redis URL is set${purpose ? ` for '${purpose}'` : ''}: set the ${keys} secret.`, 'UNAVAILABLE', {
44
+ reason: 'redis-url-not-set',
45
+ retryable: false,
46
+ details: { purpose: purpose ?? null }
47
+ });
48
+ }
49
+ /**
50
+ * Centralized Redis connection manager for proper cleanup
51
+ */
52
+ export class RedisConnectionManager {
53
+ connections = [];
54
+ closeAllPromise = null;
55
+ runtime;
56
+ createClient;
57
+ constructor(runtimeOrCreateClient, createClient) {
58
+ if (runtimeOrCreateClient instanceof Function) {
59
+ this.createClient = runtimeOrCreateClient;
60
+ }
61
+ else {
62
+ this.runtime = runtimeOrCreateClient;
63
+ this.createClient = createClient ?? (() => { throw new CapabilityError('Compose the Redis Node plugin to connect', 'UNAVAILABLE', { reason: 'redis-provider-unavailable' }); });
64
+ }
65
+ }
66
+ createBuildClient() {
67
+ // The host factory creates a lazy client; no socket is opened.
68
+ const client = this.createClient('', { lazyConnect: true });
69
+ const transaction = new Proxy(client, {
70
+ get(_target, prop) {
71
+ if (prop === 'then')
72
+ return undefined;
73
+ if (prop === 'exec')
74
+ return () => Promise.resolve([]);
75
+ return () => transaction;
76
+ }
77
+ });
78
+ const builder = new Proxy(client, {
79
+ get(target, prop) {
80
+ if (prop === 'then')
81
+ return undefined;
82
+ if (prop === 'multi' || prop === 'pipeline')
83
+ return () => transaction;
84
+ if (prop === 'exec')
85
+ return () => Promise.resolve([]);
86
+ if (prop === 'status')
87
+ return 'end';
88
+ // SAFETY: Proxy keys address the vendor target; unknown keys preserve undefined.
89
+ if (target[prop] instanceof Function)
90
+ return () => Promise.resolve();
91
+ // SAFETY: Preserve the vendor's property values for arbitrary proxy keys.
92
+ return target[prop];
93
+ }
94
+ });
95
+ return builder;
96
+ }
97
+ log(level, message, meta, activeRuntime) {
98
+ const targetRuntime = activeRuntime ?? this.runtime;
99
+ if (targetRuntime && !targetRuntime.lifecycle.signal.aborted)
100
+ getLogger('redis', targetRuntime)[level](message, meta);
101
+ }
102
+ logDebug(message, meta, runtime) {
103
+ this.log('debug', message, meta, runtime);
104
+ }
105
+ logInfo(message, meta, runtime) {
106
+ this.log('info', message, meta, runtime);
107
+ }
108
+ logWarn(message, meta, runtime) {
109
+ this.log('warn', message, meta, runtime);
110
+ }
111
+ /**
112
+ * Create a new Redis connection with cleanup tracking. The caller supplies
113
+ * the URL (a resolved credential: `resolveRedisUrl`) and the runtime whose
114
+ * declared scope decides whether this is a build host.
115
+ */
116
+ createConnection(runtime, url, options) {
117
+ if (!this.runtime) {
118
+ this.runtime = runtime;
119
+ }
120
+ // A declared finite build (prerender) gets a client that does nothing.
121
+ if (isDeclaredBuildHost(runtime)) {
122
+ return this.createBuildClient();
123
+ }
124
+ if (this.closeAllPromise) {
125
+ throw new Error('Cannot create a Redis connection while disposal is in progress');
126
+ }
127
+ const defaults = RedisSettingsSchema.parse({});
128
+ const redis = this.createClient(url, {
129
+ // Defaults; `getRedisConnection` passes the declared `redis` settings.
130
+ maxRetriesPerRequest: defaults.maxRetriesPerRequest,
131
+ enableReadyCheck: defaults.enableReadyCheck,
132
+ retryStrategy: (times) => {
133
+ const delay = Math.min(times * 50, 2000);
134
+ this.logDebug(`Redis reconnecting (attempt ${times})...`, undefined, runtime);
135
+ return delay;
136
+ },
137
+ reconnectOnError: (err) => {
138
+ // Reconnect and resend command on READONLY (failover scenario)
139
+ if (err.message.includes('READONLY')) {
140
+ return 2; // reconnect and resend the failed command
141
+ }
142
+ // Reconnect on NOAUTH - happens when port-forward drops/reconnects
143
+ // Return 2 to reconnect and resend the command
144
+ if (err.message.includes('NOAUTH')) {
145
+ return 2;
146
+ }
147
+ return false;
148
+ },
149
+ // Override with provided options (e.g., maxRetriesPerRequest: null for BullMQ)
150
+ ...options
151
+ });
152
+ // Track connection for cleanup
153
+ this.connections.push(redis);
154
+ // Set up comprehensive error handling
155
+ redis.on('error', (error) => {
156
+ settleNow(() => runtime.diagnostics.error('Redis connection error', { scope: 'redis', plugin: 'redis', error: valueFreeFailure(error) }));
157
+ });
158
+ redis.on('reconnecting', (delay) => {
159
+ this.logDebug(`Redis reconnecting in ${delay}ms...`, undefined, runtime);
160
+ });
161
+ redis.on('connect', () => {
162
+ // Silent connection established
163
+ });
164
+ redis.on('ready', () => {
165
+ // Silent connection ready
166
+ });
167
+ return redis;
168
+ }
169
+ /**
170
+ * Gracefully close all tracked connections
171
+ */
172
+ closeAllConnections() {
173
+ if (this.closeAllPromise)
174
+ return this.closeAllPromise;
175
+ const activeConnections = [...this.connections];
176
+ if (activeConnections.length === 0)
177
+ return Promise.resolve();
178
+ this.logInfo(`Closing ${activeConnections.length} Redis connections...`);
179
+ const closeOperation = (async () => {
180
+ const results = await Promise.allSettled(activeConnections.map(async (redis, index) => {
181
+ if (redis.status === 'end') {
182
+ this.removeConnection(redis);
183
+ return;
184
+ }
185
+ const quit = await settle(() => redis.quit());
186
+ if (quit.ok) {
187
+ this.removeConnection(redis);
188
+ return;
189
+ }
190
+ const disconnect = settleNow(() => redis.disconnect());
191
+ if (disconnect.ok)
192
+ this.removeConnection(redis);
193
+ const failures = [new Error('Redis quit failed', { cause: valueFreeFailure(quit.cause) })];
194
+ if (!disconnect.ok) {
195
+ failures.push(new Error('Redis disconnect failed', { cause: valueFreeFailure(disconnect.cause) }));
196
+ }
197
+ throw new AggregateError(failures, `Redis connection ${index + 1} cleanup failed`);
198
+ }));
199
+ const failures = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
200
+ if (failures.length > 0) {
201
+ throw new AggregateError(failures, `Redis disposal failed for ${failures.length} connection${failures.length === 1 ? '' : 's'}`);
202
+ }
203
+ this.logInfo('All Redis connections closed');
204
+ })();
205
+ this.closeAllPromise = closeOperation.finally(() => {
206
+ this.closeAllPromise = null;
207
+ });
208
+ return this.closeAllPromise;
209
+ }
210
+ /**
211
+ * Get count of active connections
212
+ */
213
+ getConnectionCount() {
214
+ return this.connections.filter((redis) => redis.status === 'ready' || redis.status === 'connecting').length;
215
+ }
216
+ /**
217
+ * Wait for a connection's own `ready` event, bounded by the caller's
218
+ * runtime lifecycle (RC07): the wait rejects `TIMEOUT wait-timeout` at the
219
+ * deadline, `CANCELLED wait-aborted` when the runtime is disposed, or with
220
+ * the connection's `error`.
221
+ */
222
+ waitForConnection(redis, lifecycle, timeoutMs = RedisSettingsSchema.parse({}).readinessTimeoutMs) {
223
+ if (redis.status === 'ready')
224
+ return Promise.resolve();
225
+ return lifecycle.wait((signal) => new Promise((resolve, reject) => {
226
+ if (signal.aborted) {
227
+ reject(signal.reason);
228
+ return;
229
+ }
230
+ const onReady = () => {
231
+ cleanup();
232
+ resolve();
233
+ };
234
+ const onError = (error) => {
235
+ cleanup();
236
+ reject(new CapabilityError('Redis connection failed', 'UNAVAILABLE', { reason: 'redis-connection-failed', cause: valueFreeFailure(error) }));
237
+ };
238
+ const onAbort = () => {
239
+ cleanup();
240
+ reject(signal.reason);
241
+ };
242
+ const cleanup = () => {
243
+ redis.off('ready', onReady);
244
+ redis.off('error', onError);
245
+ signal.removeEventListener('abort', onAbort);
246
+ };
247
+ redis.once('ready', onReady);
248
+ redis.once('error', onError);
249
+ signal.addEventListener('abort', onAbort, { once: true });
250
+ }), { timeoutMs, reason: 'redis-connection-ready' });
251
+ }
252
+ /**
253
+ * Check if a connection is healthy
254
+ */
255
+ isConnectionHealthy(redis) {
256
+ return redis.status === 'ready';
257
+ }
258
+ /**
259
+ * Force disconnect all connections (emergency cleanup)
260
+ */
261
+ forceDisconnectAll() {
262
+ this.logWarn('Force disconnecting all Redis connections');
263
+ const failures = [];
264
+ for (const [index, redis] of [...this.connections].entries()) {
265
+ const disconnected = settleNow(() => redis.disconnect());
266
+ if (disconnected.ok) {
267
+ this.removeConnection(redis);
268
+ }
269
+ else {
270
+ failures.push(new Error(`Failed to force-disconnect Redis connection ${index + 1}`, {
271
+ cause: valueFreeFailure(disconnected.cause)
272
+ }));
273
+ }
274
+ }
275
+ if (failures.length > 0) {
276
+ throw new AggregateError(failures, 'One or more Redis connections could not be disconnected');
277
+ }
278
+ }
279
+ removeConnection(redis) {
280
+ const index = this.connections.indexOf(redis);
281
+ if (index >= 0)
282
+ this.connections.splice(index, 1);
283
+ }
284
+ }
285
+ export function redisClientFor(runtime) {
286
+ const client = tryGetVibesClient('redis', runtime);
287
+ if (!client)
288
+ throw new CapabilityError('Activate the Redis plugin before synchronous access', 'UNAVAILABLE', { reason: 'redis-client-unavailable' });
289
+ return client;
290
+ }
291
+ export function redisManagerFor(runtime) {
292
+ return redisClientFor(runtime).manager;
293
+ }
294
+ export async function disposeRedisConnections(runtime) {
295
+ await redisClientFor(runtime).dispose();
296
+ }
297
+ /**
298
+ * @deprecated Process-global shutdown handlers were removed from this reusable
299
+ * package. Compose `redisPlugin`: the runtime's disposal closes that
300
+ * runtime's connections (`disposeRedisConnections(runtime)`).
301
+ */
302
+ export function setupRedisShutdownHandlers() {
303
+ throw new Error('setupRedisShutdownHandlers() no longer installs process handlers; register disposeRedisConnections() with the executable host lifecycle');
304
+ }
305
+ /**
306
+ * A Redis connection on `runtime`, tracked by the manager `runtime` owns: the URL is the
307
+ * `REDIS_URL` credential and the retry and ready-check settings are the
308
+ * `integrations.redis` manifest; `options` wins per field.
309
+ */
310
+ export async function getRedisConnection(runtime, options) {
311
+ if (isDeclaredBuildHost(runtime))
312
+ return redisManagerFor(runtime).createBuildClient();
313
+ const url = await resolveRedisUrl(runtime);
314
+ const settings = await (await getVibesClient('config', runtime)).read(redisSettingsManifest);
315
+ return redisManagerFor(runtime).createConnection(runtime, url, {
316
+ maxRetriesPerRequest: settings.maxRetriesPerRequest,
317
+ enableReadyCheck: settings.enableReadyCheck,
318
+ ...options
319
+ });
320
+ }
321
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Integrations Redis plugin
3
+ *
4
+ * Declares the `integrations.redis` settings manifest, contributes the Redis
5
+ * and ioredis OpenTelemetry instrumentations to logging's instrumentation
6
+ * port, and registers the runtime-owned Node Redis semantic client.
7
+ */
8
+ export declare const redisNodePlugin: import("@vibesdotdev/kernel").RuntimePlugin;
9
+ export default redisNodePlugin;
10
+ //# sourceMappingURL=redis.consumer.plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.consumer.plugin.d.ts","sourceRoot":"","sources":["../src/redis.consumer.plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,eAAO,MAAM,eAAe,6CAoB1B,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Integrations Redis plugin
3
+ *
4
+ * Declares the `integrations.redis` settings manifest, contributes the Redis
5
+ * and ioredis OpenTelemetry instrumentations to logging's instrumentation
6
+ * port, and registers the runtime-owned Node Redis semantic client.
7
+ */
8
+ import { getVibesClient } from '@vibesdotdev/kernel/client';
9
+ import { createRuntimePlugin, loader } from '@vibesdotdev/kernel/factory';
10
+ import redisSettingsDescriptor from "./config.js";
11
+ import { IOREDIS_TELEMETRY_INSTRUMENTATION_ID, REDIS_TELEMETRY_INSTRUMENTATION_ID, ioredisTelemetryInstrumentationDescriptor, redisTelemetryInstrumentationDescriptor } from "./telemetry.js";
12
+ export const redisNodePlugin = createRuntimePlugin({
13
+ id: 'integrations-redis-consumer',
14
+ name: 'Integrations Redis',
15
+ description: 'Redis connection registry, instrumented client and the Workers scheduler lock.',
16
+ descriptors: [
17
+ redisSettingsDescriptor,
18
+ { kind: 'runtime/client', id: 'redis' },
19
+ ioredisTelemetryInstrumentationDescriptor,
20
+ redisTelemetryInstrumentationDescriptor
21
+ ],
22
+ loaders: [
23
+ loader('redis', { kind: 'runtime/client' }, () => import("./client.node.js")),
24
+ loader(IOREDIS_TELEMETRY_INSTRUMENTATION_ID, { kind: 'observability/telemetry-instrumentation' }, () => import("./telemetry-ioredis.impl.js")),
25
+ loader(REDIS_TELEMETRY_INSTRUMENTATION_ID, { kind: 'observability/telemetry-instrumentation' }, () => import("./telemetry-redis.impl.js"))
26
+ ],
27
+ onActivate: async (runtime) => { await getVibesClient('redis', runtime); }
28
+ });
29
+ export default redisNodePlugin;
30
+ //# sourceMappingURL=redis.consumer.plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.consumer.plugin.js","sourceRoot":"","sources":["../src/redis.consumer.plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,uBAAuB,MAAM,aAAa,CAAC;AAClD,OAAO,EACN,oCAAoC,EACpC,kCAAkC,EAClC,yCAAyC,EACzC,uCAAuC,EACvC,MAAM,gBAAgB,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC;IAClD,EAAE,EAAE,6BAA6B;IACjC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,gFAAgF;IAC7F,WAAW,EAAE;QACZ,uBAAuB;QACvB,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,OAAO,EAAE;QACvC,yCAAyC;QACzC,uCAAuC;KACvC;IACD,OAAO,EAAE;QACT,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5E,MAAM,CAAC,oCAAoC,EAAE,EAAE,IAAI,EAAE,yCAAyC,EAAE,EAAE,GAAG,EAAE,CACtG,MAAM,CAAC,6BAA6B,CAAC,CACrC;QACD,MAAM,CAAC,kCAAkC,EAAE,EAAE,IAAI,EAAE,yCAAyC,EAAE,EAAE,GAAG,EAAE,CACpG,MAAM,CAAC,2BAA2B,CAAC,CACnC;KACD;IACD,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CAC1E,CAAC,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const redisPlugin: import("@vibesdotdev/kernel").RuntimePlugin;
2
+ export default redisPlugin;
3
+ //# sourceMappingURL=redis.plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.plugin.d.ts","sourceRoot":"","sources":["../src/redis.plugin.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,6CAMtB,CAAC;AACH,eAAe,WAAW,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { createRuntimePlugin, loader } from '@vibesdotdev/kernel/factory';
2
+ import { getVibesClient } from '@vibesdotdev/kernel/client';
3
+ import redisSettingsDescriptor from "./config.js";
4
+ export const redisPlugin = createRuntimePlugin({
5
+ id: 'integrations-redis',
6
+ name: 'Redis contract',
7
+ descriptors: [redisSettingsDescriptor, { kind: 'runtime/client', id: 'redis' }],
8
+ loaders: [loader('redis', { kind: 'runtime/client' }, () => import("./client.js").then(m => ({ impl: m.RedisClient })))],
9
+ onActivate: async (runtime) => { await getVibesClient('redis', runtime); }
10
+ });
11
+ export default redisPlugin;
12
+ //# sourceMappingURL=redis.plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.plugin.js","sourceRoot":"","sources":["../src/redis.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,uBAAuB,MAAM,aAAa,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAC;IAC9C,EAAE,EAAE,oBAAoB;IACxB,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IAC/E,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IACxH,UAAU,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACxE,CAAC,CAAC;AACH,eAAe,WAAW,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Redis implementation of the Workers scheduler lock port
3
+ * (`SchedulerLock` from `@vibesdotdev/workers/scheduler/lock`), moved from
4
+ * `@vibesdotdev/workers/scheduler/lock` (RC09).
5
+ *
6
+ * `SET key token NX PX ttl` to acquire; a token-checked Lua `DEL` to release.
7
+ * Not a distributed redlock: good for single-runner maintenance tasks. A
8
+ * release whose store call fails rejects with that failure (it is not read as
9
+ * "someone else holds it").
10
+ */
11
+ import type { SchedulerLock } from '@vibesdotdev/workers/scheduler/lock';
12
+ import { type SchedulerLockStore } from './schemas/lock.ts';
13
+ export type { SchedulerLockStore } from './schemas/lock.ts';
14
+ export declare class RedisSchedulerLock implements SchedulerLock {
15
+ private readonly redis;
16
+ constructor(redis: SchedulerLockStore);
17
+ acquire(key: string, ttlMs: number): Promise<string | null>;
18
+ release(key: string, token: string): Promise<boolean>;
19
+ }
20
+ //# sourceMappingURL=scheduler-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-lock.d.ts","sourceRoot":"","sources":["../src/scheduler-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,EAAkD,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5G,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQ5D,qBAAa,kBAAmB,YAAW,aAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,kBAAkB;IAEhD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAO3D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAK3D"}