@pipeline-builder/api-core 3.4.76 → 3.4.77

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.
@@ -1,4 +1,5 @@
1
1
  export * from './cache-service.js';
2
+ export * from './leader-lock.js';
2
3
  export * from './compliance-client.js';
3
4
  export * from './compliance-event-subscriber.js';
4
5
  export * from './entity-events.js';
@@ -1,6 +1,7 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  export * from './cache-service.js';
4
+ export * from './leader-lock.js';
4
5
  export * from './compliance-client.js';
5
6
  export * from './compliance-event-subscriber.js';
6
7
  export * from './entity-events.js';
@@ -9,4 +10,4 @@ export { DEFAULT_MAX_RETRIES, DEFAULT_RETRY_DELAY_MS, DEFAULT_MAX_RATE_LIMIT_RET
9
10
  export * from './quota.js';
10
11
  export * from './remote-audit-client.js';
11
12
  export { enqueueComplianceEvent, registerComplianceQueueBackend } from './compliance-queue.js';
12
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixzQkFBc0IsRUFDdEIsOEJBQThCLEVBQzlCLGdCQUFnQixFQUNoQixxQkFBcUIsRUFDckIsYUFBYSxFQUNiLGdCQUFnQixFQUNoQixxQkFBcUIsR0FDdEIsTUFBTSxxQkFBcUIsQ0FBQztBQUU3QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSw4QkFBOEIsRUFBd0IsTUFBTSx1QkFBdUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQgKiBmcm9tICcuL2NhY2hlLXNlcnZpY2UuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb21wbGlhbmNlLWNsaWVudC5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2NvbXBsaWFuY2UtZXZlbnQtc3Vic2NyaWJlci5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2VudGl0eS1ldmVudHMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9odHRwLWNsaWVudC5qcyc7XG5leHBvcnQge1xuICBERUZBVUxUX01BWF9SRVRSSUVTLFxuICBERUZBVUxUX1JFVFJZX0RFTEFZX01TLFxuICBERUZBVUxUX01BWF9SQVRFX0xJTUlUX1JFVFJJRVMsXG4gIGNhbGN1bGF0ZUJhY2tvZmYsXG4gIGlzVHJhbnNpZW50U3RhdHVzQ29kZSxcbiAgaXNSYXRlTGltaXRlZCxcbiAgZ2V0UmV0cnlEZWNpc2lvbixcbiAgZ2V0RXJyb3JSZXRyeURlY2lzaW9uLFxufSBmcm9tICcuL3JldHJ5LXN0cmF0ZWd5LmpzJztcbmV4cG9ydCB0eXBlIHsgUmV0cnlDb25maWcsIFJldHJ5RGVjaXNpb24gfSBmcm9tICcuL3JldHJ5LXN0cmF0ZWd5LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vcXVvdGEuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9yZW1vdGUtYXVkaXQtY2xpZW50LmpzJztcbmV4cG9ydCB7IGVucXVldWVDb21wbGlhbmNlRXZlbnQsIHJlZ2lzdGVyQ29tcGxpYW5jZVF1ZXVlQmFja2VuZCwgdHlwZSBDb21wbGlhbmNlRXZlbnQgfSBmcm9tICcuL2NvbXBsaWFuY2UtcXVldWUuanMnO1xuIl19
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLGtDQUFrQyxDQUFDO0FBQ2pELGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLHNCQUFzQixFQUN0Qiw4QkFBOEIsRUFDOUIsZ0JBQWdCLEVBQ2hCLHFCQUFxQixFQUNyQixhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLHFCQUFxQixHQUN0QixNQUFNLHFCQUFxQixDQUFDO0FBRTdCLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLDhCQUE4QixFQUF3QixNQUFNLHVCQUF1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmV4cG9ydCAqIGZyb20gJy4vY2FjaGUtc2VydmljZS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2xlYWRlci1sb2NrLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vY29tcGxpYW5jZS1jbGllbnQuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb21wbGlhbmNlLWV2ZW50LXN1YnNjcmliZXIuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9lbnRpdHktZXZlbnRzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vaHR0cC1jbGllbnQuanMnO1xuZXhwb3J0IHtcbiAgREVGQVVMVF9NQVhfUkVUUklFUyxcbiAgREVGQVVMVF9SRVRSWV9ERUxBWV9NUyxcbiAgREVGQVVMVF9NQVhfUkFURV9MSU1JVF9SRVRSSUVTLFxuICBjYWxjdWxhdGVCYWNrb2ZmLFxuICBpc1RyYW5zaWVudFN0YXR1c0NvZGUsXG4gIGlzUmF0ZUxpbWl0ZWQsXG4gIGdldFJldHJ5RGVjaXNpb24sXG4gIGdldEVycm9yUmV0cnlEZWNpc2lvbixcbn0gZnJvbSAnLi9yZXRyeS1zdHJhdGVneS5qcyc7XG5leHBvcnQgdHlwZSB7IFJldHJ5Q29uZmlnLCBSZXRyeURlY2lzaW9uIH0gZnJvbSAnLi9yZXRyeS1zdHJhdGVneS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3F1b3RhLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vcmVtb3RlLWF1ZGl0LWNsaWVudC5qcyc7XG5leHBvcnQgeyBlbnF1ZXVlQ29tcGxpYW5jZUV2ZW50LCByZWdpc3RlckNvbXBsaWFuY2VRdWV1ZUJhY2tlbmQsIHR5cGUgQ29tcGxpYW5jZUV2ZW50IH0gZnJvbSAnLi9jb21wbGlhbmNlLXF1ZXVlLmpzJztcbiJdfQ==
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Minimal Redis client surface needed for a leader lock (a subset of ioredis).
3
+ * `set` is variadic so callers can pass `'PX', ttl, 'NX'`.
4
+ */
5
+ export interface LockRedis {
6
+ set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
7
+ get(key: string): Promise<string | null>;
8
+ del(...keys: string[]): Promise<number>;
9
+ }
10
+ /**
11
+ * Run `fn` only if this process wins a short-lived distributed lock — the
12
+ * across-pods "single runner" guard for periodic jobs (digest flushes, etc.).
13
+ *
14
+ * Uses `SET key token NX PX ttl`, so exactly one holder runs per window and the
15
+ * lock auto-expires if that holder dies mid-run (no stuck lock). The lock is
16
+ * released on completion, but only if we still own it — a slower predecessor
17
+ * never deletes a successor's lock. `ttlMs` should comfortably exceed one run.
18
+ *
19
+ * @returns true if we held the lock and ran `fn`; false if another holder did.
20
+ */
21
+ export declare function withLeaderLock(redis: LockRedis, key: string, ttlMs: number, fn: () => Promise<void>): Promise<boolean>;
@@ -0,0 +1,36 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { randomUUID } from 'crypto';
4
+ /**
5
+ * Run `fn` only if this process wins a short-lived distributed lock — the
6
+ * across-pods "single runner" guard for periodic jobs (digest flushes, etc.).
7
+ *
8
+ * Uses `SET key token NX PX ttl`, so exactly one holder runs per window and the
9
+ * lock auto-expires if that holder dies mid-run (no stuck lock). The lock is
10
+ * released on completion, but only if we still own it — a slower predecessor
11
+ * never deletes a successor's lock. `ttlMs` should comfortably exceed one run.
12
+ *
13
+ * @returns true if we held the lock and ran `fn`; false if another holder did.
14
+ */
15
+ export async function withLeaderLock(redis, key, ttlMs, fn) {
16
+ const token = randomUUID();
17
+ const acquired = await redis.set(key, token, 'PX', ttlMs, 'NX');
18
+ if (acquired !== 'OK')
19
+ return false;
20
+ try {
21
+ await fn();
22
+ }
23
+ finally {
24
+ // Release only if the lock is still ours — if our run overran the TTL and
25
+ // another holder took over, deleting here would free their lock early.
26
+ try {
27
+ if ((await redis.get(key)) === token)
28
+ await redis.del(key);
29
+ }
30
+ catch {
31
+ // Best-effort: the TTL expires the lock regardless.
32
+ }
33
+ }
34
+ return true;
35
+ }
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVhZGVyLWxvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvbGVhZGVyLWxvY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBWXBDOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsS0FBZ0IsRUFDaEIsR0FBVyxFQUNYLEtBQWEsRUFDYixFQUF1QjtJQUV2QixNQUFNLEtBQUssR0FBRyxVQUFVLEVBQUUsQ0FBQztJQUMzQixNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2hFLElBQUksUUFBUSxLQUFLLElBQUk7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUVwQyxJQUFJLENBQUM7UUFDSCxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ2IsQ0FBQztZQUFTLENBQUM7UUFDVCwwRUFBMEU7UUFDMUUsdUVBQXVFO1FBQ3ZFLElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxLQUFLO2dCQUFFLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1Asb0RBQW9EO1FBQ3RELENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuXG4vKipcbiAqIE1pbmltYWwgUmVkaXMgY2xpZW50IHN1cmZhY2UgbmVlZGVkIGZvciBhIGxlYWRlciBsb2NrIChhIHN1YnNldCBvZiBpb3JlZGlzKS5cbiAqIGBzZXRgIGlzIHZhcmlhZGljIHNvIGNhbGxlcnMgY2FuIHBhc3MgYCdQWCcsIHR0bCwgJ05YJ2AuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTG9ja1JlZGlzIHtcbiAgc2V0KGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pOiBQcm9taXNlPHVua25vd24+O1xuICBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+O1xuICBkZWwoLi4ua2V5czogc3RyaW5nW10pOiBQcm9taXNlPG51bWJlcj47XG59XG5cbi8qKlxuICogUnVuIGBmbmAgb25seSBpZiB0aGlzIHByb2Nlc3Mgd2lucyBhIHNob3J0LWxpdmVkIGRpc3RyaWJ1dGVkIGxvY2sg4oCUIHRoZVxuICogYWNyb3NzLXBvZHMgXCJzaW5nbGUgcnVubmVyXCIgZ3VhcmQgZm9yIHBlcmlvZGljIGpvYnMgKGRpZ2VzdCBmbHVzaGVzLCBldGMuKS5cbiAqXG4gKiBVc2VzIGBTRVQga2V5IHRva2VuIE5YIFBYIHR0bGAsIHNvIGV4YWN0bHkgb25lIGhvbGRlciBydW5zIHBlciB3aW5kb3cgYW5kIHRoZVxuICogbG9jayBhdXRvLWV4cGlyZXMgaWYgdGhhdCBob2xkZXIgZGllcyBtaWQtcnVuIChubyBzdHVjayBsb2NrKS4gVGhlIGxvY2sgaXNcbiAqIHJlbGVhc2VkIG9uIGNvbXBsZXRpb24sIGJ1dCBvbmx5IGlmIHdlIHN0aWxsIG93biBpdCDigJQgYSBzbG93ZXIgcHJlZGVjZXNzb3JcbiAqIG5ldmVyIGRlbGV0ZXMgYSBzdWNjZXNzb3IncyBsb2NrLiBgdHRsTXNgIHNob3VsZCBjb21mb3J0YWJseSBleGNlZWQgb25lIHJ1bi5cbiAqXG4gKiBAcmV0dXJucyB0cnVlIGlmIHdlIGhlbGQgdGhlIGxvY2sgYW5kIHJhbiBgZm5gOyBmYWxzZSBpZiBhbm90aGVyIGhvbGRlciBkaWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoTGVhZGVyTG9jayhcbiAgcmVkaXM6IExvY2tSZWRpcyxcbiAga2V5OiBzdHJpbmcsXG4gIHR0bE1zOiBudW1iZXIsXG4gIGZuOiAoKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IHRva2VuID0gcmFuZG9tVVVJRCgpO1xuICBjb25zdCBhY3F1aXJlZCA9IGF3YWl0IHJlZGlzLnNldChrZXksIHRva2VuLCAnUFgnLCB0dGxNcywgJ05YJyk7XG4gIGlmIChhY3F1aXJlZCAhPT0gJ09LJykgcmV0dXJuIGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgYXdhaXQgZm4oKTtcbiAgfSBmaW5hbGx5IHtcbiAgICAvLyBSZWxlYXNlIG9ubHkgaWYgdGhlIGxvY2sgaXMgc3RpbGwgb3VycyDigJQgaWYgb3VyIHJ1biBvdmVycmFuIHRoZSBUVEwgYW5kXG4gICAgLy8gYW5vdGhlciBob2xkZXIgdG9vayBvdmVyLCBkZWxldGluZyBoZXJlIHdvdWxkIGZyZWUgdGhlaXIgbG9jayBlYXJseS5cbiAgICB0cnkge1xuICAgICAgaWYgKChhd2FpdCByZWRpcy5nZXQoa2V5KSkgPT09IHRva2VuKSBhd2FpdCByZWRpcy5kZWwoa2V5KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIEJlc3QtZWZmb3J0OiB0aGUgVFRMIGV4cGlyZXMgdGhlIGxvY2sgcmVnYXJkbGVzcy5cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG4iXX0=
package/package.json CHANGED
@@ -85,7 +85,7 @@
85
85
  "access": "public",
86
86
  "registry": "https://registry.npmjs.org/"
87
87
  },
88
- "version": "3.4.76",
88
+ "version": "3.4.77",
89
89
  "bugs": {
90
90
  "url": "https://github.com/mwashburn160/pipeline-builder/issues"
91
91
  },