@blokjs/runner 0.6.20 → 0.7.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/dist/Blok.d.ts +2 -0
- package/dist/Blok.js +42 -110
- package/dist/Blok.js.map +1 -1
- package/dist/DefaultLogger.d.ts +13 -0
- package/dist/DefaultLogger.js +25 -0
- package/dist/DefaultLogger.js.map +1 -1
- package/dist/RunnerSteps.d.ts +23 -0
- package/dist/RunnerSteps.js +128 -87
- package/dist/RunnerSteps.js.map +1 -1
- package/dist/SubworkflowNode.js +19 -0
- package/dist/SubworkflowNode.js.map +1 -1
- package/dist/TriggerBase.d.ts +12 -0
- package/dist/TriggerBase.js +216 -181
- package/dist/TriggerBase.js.map +1 -1
- package/dist/adapters/grpc/GrpcRuntimeAdapter.d.ts +9 -0
- package/dist/adapters/grpc/GrpcRuntimeAdapter.js +76 -6
- package/dist/adapters/grpc/GrpcRuntimeAdapter.js.map +1 -1
- package/dist/index.d.ts +4 -39
- package/dist/index.js +7 -32
- package/dist/index.js.map +1 -1
- package/dist/monitoring/JanitorMetrics.d.ts +3 -0
- package/dist/monitoring/JanitorMetrics.js +11 -0
- package/dist/monitoring/JanitorMetrics.js.map +1 -1
- package/dist/monitoring/ProcessErrorMetrics.d.ts +32 -0
- package/dist/monitoring/ProcessErrorMetrics.js +43 -0
- package/dist/monitoring/ProcessErrorMetrics.js.map +1 -0
- package/dist/monitoring/PrometheusMetricsBridge.d.ts +7 -0
- package/dist/monitoring/PrometheusMetricsBridge.js +8 -2
- package/dist/monitoring/PrometheusMetricsBridge.js.map +1 -1
- package/dist/monitoring/SubworkflowMetrics.d.ts +25 -0
- package/dist/monitoring/SubworkflowMetrics.js +38 -0
- package/dist/monitoring/SubworkflowMetrics.js.map +1 -0
- package/dist/observability/ErrorSink.d.ts +23 -0
- package/dist/observability/ErrorSink.js +32 -0
- package/dist/observability/ErrorSink.js.map +1 -0
- package/dist/observability/SentryIntegration.d.ts +9 -0
- package/dist/observability/SentryIntegration.js +31 -0
- package/dist/observability/SentryIntegration.js.map +1 -0
- package/dist/scheduling/DebounceCoordinator.d.ts +7 -53
- package/dist/scheduling/DebounceCoordinator.js +8 -207
- package/dist/scheduling/DebounceCoordinator.js.map +1 -1
- package/dist/tracing/InMemoryRunStore.d.ts +5 -1
- package/dist/tracing/InMemoryRunStore.js +14 -0
- package/dist/tracing/InMemoryRunStore.js.map +1 -1
- package/dist/tracing/Janitor.js +3 -0
- package/dist/tracing/Janitor.js.map +1 -1
- package/dist/tracing/PostgresRunStore.d.ts +4 -1
- package/dist/tracing/PostgresRunStore.js +73 -3
- package/dist/tracing/PostgresRunStore.js.map +1 -1
- package/dist/tracing/RunStore.d.ts +17 -1
- package/dist/tracing/RunTracker.d.ts +13 -34
- package/dist/tracing/RunTracker.js +62 -32
- package/dist/tracing/RunTracker.js.map +1 -1
- package/dist/tracing/SqliteRunStore.d.ts +4 -1
- package/dist/tracing/SqliteRunStore.js +60 -0
- package/dist/tracing/SqliteRunStore.js.map +1 -1
- package/dist/tracing/TraceRouter.d.ts +13 -0
- package/dist/tracing/TraceRouter.js +43 -11
- package/dist/tracing/TraceRouter.js.map +1 -1
- package/dist/tracing/TracingLogger.js +22 -0
- package/dist/tracing/TracingLogger.js.map +1 -1
- package/dist/tracing/createStore.js +51 -22
- package/dist/tracing/createStore.js.map +1 -1
- package/dist/tracing/types.d.ts +22 -0
- package/dist/types/GlobalOptions.d.ts +5 -7
- package/dist/workflow/WorkflowNormalizer.js +63 -0
- package/dist/workflow/WorkflowNormalizer.js.map +1 -1
- package/package.json +7 -4
- package/dist/cache/NodeResultCache.d.ts +0 -286
- package/dist/cache/NodeResultCache.js +0 -506
- package/dist/cache/NodeResultCache.js.map +0 -1
- package/dist/cache/index.d.ts +0 -1
- package/dist/cache/index.js +0 -2
- package/dist/cache/index.js.map +0 -1
- package/dist/concurrency/ConcurrencyBackend.d.ts +0 -61
- package/dist/concurrency/ConcurrencyBackend.js +0 -20
- package/dist/concurrency/ConcurrencyBackend.js.map +0 -1
- package/dist/concurrency/NatsKvConcurrencyBackend.d.ts +0 -64
- package/dist/concurrency/NatsKvConcurrencyBackend.js +0 -310
- package/dist/concurrency/NatsKvConcurrencyBackend.js.map +0 -1
- package/dist/concurrency/RedisConcurrencyBackend.d.ts +0 -64
- package/dist/concurrency/RedisConcurrencyBackend.js +0 -374
- package/dist/concurrency/RedisConcurrencyBackend.js.map +0 -1
- package/dist/concurrency/createConcurrencyBackend.d.ts +0 -24
- package/dist/concurrency/createConcurrencyBackend.js +0 -38
- package/dist/concurrency/createConcurrencyBackend.js.map +0 -1
- package/dist/graphql/GraphQLSchemaGenerator.d.ts +0 -129
- package/dist/graphql/GraphQLSchemaGenerator.js +0 -425
- package/dist/graphql/GraphQLSchemaGenerator.js.map +0 -1
- package/dist/integrations/APMIntegration.d.ts +0 -141
- package/dist/integrations/APMIntegration.js +0 -212
- package/dist/integrations/APMIntegration.js.map +0 -1
- package/dist/integrations/AzureMonitorIntegration.d.ts +0 -118
- package/dist/integrations/AzureMonitorIntegration.js +0 -254
- package/dist/integrations/AzureMonitorIntegration.js.map +0 -1
- package/dist/integrations/CloudWatchIntegration.d.ts +0 -135
- package/dist/integrations/CloudWatchIntegration.js +0 -293
- package/dist/integrations/CloudWatchIntegration.js.map +0 -1
- package/dist/integrations/SentryIntegration.d.ts +0 -153
- package/dist/integrations/SentryIntegration.js +0 -200
- package/dist/integrations/SentryIntegration.js.map +0 -1
- package/dist/integrations/index.d.ts +0 -19
- package/dist/integrations/index.js +0 -16
- package/dist/integrations/index.js.map +0 -1
- package/dist/marketplace/RuntimeAutoScaler.d.ts +0 -148
- package/dist/marketplace/RuntimeAutoScaler.js +0 -366
- package/dist/marketplace/RuntimeAutoScaler.js.map +0 -1
- package/dist/marketplace/RuntimeCatalog.d.ts +0 -180
- package/dist/marketplace/RuntimeCatalog.js +0 -339
- package/dist/marketplace/RuntimeCatalog.js.map +0 -1
- package/dist/marketplace/RuntimeDiscovery.d.ts +0 -86
- package/dist/marketplace/RuntimeDiscovery.js +0 -231
- package/dist/marketplace/RuntimeDiscovery.js.map +0 -1
- package/dist/marketplace/RuntimeHealthMonitor.d.ts +0 -100
- package/dist/marketplace/RuntimeHealthMonitor.js +0 -241
- package/dist/marketplace/RuntimeHealthMonitor.js.map +0 -1
- package/dist/marketplace/RuntimeMetricsDashboard.d.ts +0 -113
- package/dist/marketplace/RuntimeMetricsDashboard.js +0 -293
- package/dist/marketplace/RuntimeMetricsDashboard.js.map +0 -1
- package/dist/openapi/OpenAPIGenerator.d.ts +0 -192
- package/dist/openapi/OpenAPIGenerator.js +0 -378
- package/dist/openapi/OpenAPIGenerator.js.map +0 -1
- package/dist/openapi/index.d.ts +0 -20
- package/dist/openapi/index.js +0 -20
- package/dist/openapi/index.js.map +0 -1
- package/dist/scheduling/DebounceBackend.d.ts +0 -108
- package/dist/scheduling/DebounceBackend.js +0 -23
- package/dist/scheduling/DebounceBackend.js.map +0 -1
- package/dist/scheduling/NatsKvDebounceBackend.d.ts +0 -53
- package/dist/scheduling/NatsKvDebounceBackend.js +0 -334
- package/dist/scheduling/NatsKvDebounceBackend.js.map +0 -1
- package/dist/scheduling/RedisDebounceBackend.d.ts +0 -49
- package/dist/scheduling/RedisDebounceBackend.js +0 -356
- package/dist/scheduling/RedisDebounceBackend.js.map +0 -1
- package/dist/scheduling/createDebounceBackend.d.ts +0 -25
- package/dist/scheduling/createDebounceBackend.js +0 -39
- package/dist/scheduling/createDebounceBackend.js.map +0 -1
- package/dist/security/ABAC.d.ts +0 -224
- package/dist/security/ABAC.js +0 -380
- package/dist/security/ABAC.js.map +0 -1
- package/dist/security/AuditLogger.d.ts +0 -242
- package/dist/security/AuditLogger.js +0 -317
- package/dist/security/AuditLogger.js.map +0 -1
- package/dist/security/AuthMiddleware.d.ts +0 -162
- package/dist/security/AuthMiddleware.js +0 -289
- package/dist/security/AuthMiddleware.js.map +0 -1
- package/dist/security/EncryptionAtRest.d.ts +0 -206
- package/dist/security/EncryptionAtRest.js +0 -236
- package/dist/security/EncryptionAtRest.js.map +0 -1
- package/dist/security/OAuthProvider.d.ts +0 -334
- package/dist/security/OAuthProvider.js +0 -719
- package/dist/security/OAuthProvider.js.map +0 -1
- package/dist/security/PIIDetector.d.ts +0 -233
- package/dist/security/PIIDetector.js +0 -354
- package/dist/security/PIIDetector.js.map +0 -1
- package/dist/security/RBAC.d.ts +0 -143
- package/dist/security/RBAC.js +0 -285
- package/dist/security/RBAC.js.map +0 -1
- package/dist/security/SecretManager.d.ts +0 -652
- package/dist/security/SecretManager.js +0 -1147
- package/dist/security/SecretManager.js.map +0 -1
- package/dist/security/TLSConfig.d.ts +0 -305
- package/dist/security/TLSConfig.js +0 -550
- package/dist/security/TLSConfig.js.map +0 -1
- package/dist/security/index.d.ts +0 -81
- package/dist/security/index.js +0 -82
- package/dist/security/index.js.map +0 -1
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tier C #1 · NATS KV-backed debounce backend.
|
|
3
|
-
*
|
|
4
|
-
* Coordinates per-(workflow, debounceKey) window state across processes
|
|
5
|
-
* via a single NATS JetStream KV value per bucket with revision-based
|
|
6
|
-
* compare-and-swap (OCC). Mirrors the storage model of
|
|
7
|
-
* `NatsKvConcurrencyBackend` but with a different document shape (one
|
|
8
|
-
* window per bucket, not a leases array).
|
|
9
|
-
*
|
|
10
|
-
* Acquire / extend / coalesce: a bounded CAS loop (10 retries) that
|
|
11
|
-
* reads → decides ownership → atomically writes. On retry exhaustion,
|
|
12
|
-
* fall back to admitting the ping as a `coalesce` against the current
|
|
13
|
-
* owner — debounce is not a safety gate, so we'd rather over-coalesce
|
|
14
|
-
* than drop pings on a contention spike.
|
|
15
|
-
*
|
|
16
|
-
* Finalize: same OCC pattern. The owning process atomically reads the
|
|
17
|
-
* doc, confirms it still owns AND `now >= scheduledAt`, and atomically
|
|
18
|
-
* deletes. On lease handoff, the owner discovers it no longer owns and
|
|
19
|
-
* abandons silently.
|
|
20
|
-
*
|
|
21
|
-
* **Owner-local payload**: this backend tracks `pingCount`,
|
|
22
|
-
* `lastPingAt`, and `scheduledAt` only — not the payload. Cross-process
|
|
23
|
-
* latest-payload-wins is a deferred follow-up.
|
|
24
|
-
*/
|
|
25
|
-
const DEFAULT_BUCKET_NAME = "blok-debounce";
|
|
26
|
-
const MAX_CAS_RETRIES = 10;
|
|
27
|
-
export function readNatsKvDebounceConfigFromEnv() {
|
|
28
|
-
const serversRaw = process.env.BLOK_DEBOUNCE_NATS_SERVERS ?? "nats://localhost:4222";
|
|
29
|
-
const servers = serversRaw
|
|
30
|
-
.split(",")
|
|
31
|
-
.map((s) => s.trim())
|
|
32
|
-
.filter(Boolean);
|
|
33
|
-
return {
|
|
34
|
-
servers,
|
|
35
|
-
token: process.env.BLOK_DEBOUNCE_NATS_TOKEN,
|
|
36
|
-
user: process.env.BLOK_DEBOUNCE_NATS_USER,
|
|
37
|
-
pass: process.env.BLOK_DEBOUNCE_NATS_PASS,
|
|
38
|
-
bucketName: process.env.BLOK_DEBOUNCE_NATS_KV_BUCKET ?? DEFAULT_BUCKET_NAME,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
export class NatsKvDebounceBackend {
|
|
42
|
-
name = "nats-kv";
|
|
43
|
-
nc = null;
|
|
44
|
-
kv = null;
|
|
45
|
-
config;
|
|
46
|
-
connected = false;
|
|
47
|
-
constructor(config) {
|
|
48
|
-
const env = readNatsKvDebounceConfigFromEnv();
|
|
49
|
-
this.config = {
|
|
50
|
-
servers: config?.servers ?? env.servers,
|
|
51
|
-
token: config?.token ?? env.token,
|
|
52
|
-
user: config?.user ?? env.user,
|
|
53
|
-
pass: config?.pass ?? env.pass,
|
|
54
|
-
bucketName: config?.bucketName ?? env.bucketName,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
async connect() {
|
|
58
|
-
if (this.connected)
|
|
59
|
-
return;
|
|
60
|
-
// Security review FW-5 parity — refuse to start in production with
|
|
61
|
-
// the default bucket name (same risk as the concurrency NATS KV
|
|
62
|
-
// bucket).
|
|
63
|
-
const blokEnv = process.env.BLOK_ENV;
|
|
64
|
-
const nodeEnv = process.env.NODE_ENV;
|
|
65
|
-
const isProd = blokEnv === "production" || nodeEnv === "production";
|
|
66
|
-
if (isProd && this.config.bucketName === DEFAULT_BUCKET_NAME) {
|
|
67
|
-
throw new Error(`[blok] NATS KV debounce backend refuses to start in production with the default bucket name ('${DEFAULT_BUCKET_NAME}'). Set BLOK_DEBOUNCE_NATS_KV_BUCKET to a deployment-unique value (e.g. 'blok-debounce-acme-prod') to prevent cross-deployment collision on a shared NATS server.`);
|
|
68
|
-
}
|
|
69
|
-
let natsModule;
|
|
70
|
-
try {
|
|
71
|
-
natsModule = (await import("nats"));
|
|
72
|
-
}
|
|
73
|
-
catch (err) {
|
|
74
|
-
throw new Error(`NatsKvDebounceBackend requires the 'nats' package. Install it: \`bun add nats\` or \`npm install nats\`. Underlying error: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
-
}
|
|
76
|
-
const connectOpts = { servers: this.config.servers };
|
|
77
|
-
if (this.config.token)
|
|
78
|
-
connectOpts.token = this.config.token;
|
|
79
|
-
if (this.config.user)
|
|
80
|
-
connectOpts.user = this.config.user;
|
|
81
|
-
if (this.config.pass)
|
|
82
|
-
connectOpts.pass = this.config.pass;
|
|
83
|
-
this.nc = await natsModule.connect(connectOpts);
|
|
84
|
-
// nats.js v2.x — KV lives at `nc.jetstream().views.kv(name)`.
|
|
85
|
-
const js = this.nc.jetstream();
|
|
86
|
-
this.kv = await js.views.kv(this.config.bucketName);
|
|
87
|
-
this.connected = true;
|
|
88
|
-
}
|
|
89
|
-
async disconnect() {
|
|
90
|
-
if (!this.connected)
|
|
91
|
-
return;
|
|
92
|
-
try {
|
|
93
|
-
await this.nc?.drain();
|
|
94
|
-
}
|
|
95
|
-
finally {
|
|
96
|
-
this.nc = null;
|
|
97
|
-
this.kv = null;
|
|
98
|
-
this.connected = false;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
bucketKey(workflowName, debounceKey) {
|
|
102
|
-
return `${this.encodeSegment(workflowName)}__${this.encodeSegment(debounceKey)}`;
|
|
103
|
-
}
|
|
104
|
-
encodeSegment(s) {
|
|
105
|
-
return s.replace(/[^-_=.a-zA-Z0-9]/g, (ch) => `_${ch.codePointAt(0)?.toString(16)}_`);
|
|
106
|
-
}
|
|
107
|
-
requireKv() {
|
|
108
|
-
if (!this.kv) {
|
|
109
|
-
throw new Error("NatsKvDebounceBackend not connected — call connect() first.");
|
|
110
|
-
}
|
|
111
|
-
return this.kv;
|
|
112
|
-
}
|
|
113
|
-
computeScheduledAt(opts, existing) {
|
|
114
|
-
const naive = opts.now + opts.delayMs;
|
|
115
|
-
const deadline = existing?.maxDelayDeadline ?? (opts.maxDelayMs !== undefined ? opts.now + opts.maxDelayMs : undefined);
|
|
116
|
-
return deadline !== undefined ? Math.min(naive, deadline) : naive;
|
|
117
|
-
}
|
|
118
|
-
async registerPing(opts) {
|
|
119
|
-
const kv = this.requireKv();
|
|
120
|
-
const key = this.bucketKey(opts.workflowName, opts.debounceKey);
|
|
121
|
-
for (let attempt = 0; attempt < MAX_CAS_RETRIES; attempt++) {
|
|
122
|
-
const entry = await this.safeGet(kv, key);
|
|
123
|
-
if (entry === "fetch-failed") {
|
|
124
|
-
// Surface but don't retry on broker outage — debounce is
|
|
125
|
-
// fail-open per the coordinator wrapper.
|
|
126
|
-
throw new Error(`registerPing fetch-failed for ${key} (attempt ${attempt + 1})`);
|
|
127
|
-
}
|
|
128
|
-
const existing = entry ? this.parseDoc(entry) : null;
|
|
129
|
-
// Owner-lease expired → treat as no existing window.
|
|
130
|
-
const ownerActive = existing !== null && existing.ownerLeaseExpiresAt > opts.now;
|
|
131
|
-
if (!existing || !ownerActive) {
|
|
132
|
-
// Take ownership — new doc or owner-lease handoff.
|
|
133
|
-
const doc = {
|
|
134
|
-
mode: opts.mode,
|
|
135
|
-
delayMs: opts.delayMs,
|
|
136
|
-
maxDelayMs: opts.maxDelayMs,
|
|
137
|
-
maxDelayDeadline: existing?.maxDelayDeadline ?? (opts.maxDelayMs !== undefined ? opts.now + opts.maxDelayMs : undefined),
|
|
138
|
-
firstPingAt: existing?.firstPingAt ?? opts.now,
|
|
139
|
-
lastPingAt: opts.now,
|
|
140
|
-
pingCount: (existing?.pingCount ?? 0) + 1,
|
|
141
|
-
activeRunId: opts.runId,
|
|
142
|
-
ownerProcessId: opts.processId,
|
|
143
|
-
ownerLeaseExpiresAt: opts.now + opts.ownerLeaseMs,
|
|
144
|
-
scheduledAt: this.computeScheduledAt(opts, existing),
|
|
145
|
-
};
|
|
146
|
-
try {
|
|
147
|
-
if (entry) {
|
|
148
|
-
await kv.update(key, JSON.stringify(doc), entry.revision);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
await kv.create(key, JSON.stringify(doc));
|
|
152
|
-
}
|
|
153
|
-
return {
|
|
154
|
-
outcome: "owner-new",
|
|
155
|
-
activeRunId: doc.activeRunId,
|
|
156
|
-
scheduledAt: doc.scheduledAt,
|
|
157
|
-
pingCount: doc.pingCount,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
continue; // CAS conflict — retry.
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// existing && ownerActive
|
|
165
|
-
if (existing.ownerProcessId === opts.processId) {
|
|
166
|
-
// We still own — extend the window.
|
|
167
|
-
const next = {
|
|
168
|
-
...existing,
|
|
169
|
-
lastPingAt: opts.now,
|
|
170
|
-
pingCount: existing.pingCount + 1,
|
|
171
|
-
ownerLeaseExpiresAt: opts.now + opts.ownerLeaseMs,
|
|
172
|
-
scheduledAt: this.computeScheduledAt(opts, existing),
|
|
173
|
-
// activeRunId stays — owner's run id from owner-new is the source of truth.
|
|
174
|
-
};
|
|
175
|
-
try {
|
|
176
|
-
await kv.update(key, JSON.stringify(next), entry?.revision ?? 0);
|
|
177
|
-
return {
|
|
178
|
-
outcome: "owner-extend",
|
|
179
|
-
activeRunId: existing.activeRunId,
|
|
180
|
-
scheduledAt: next.scheduledAt,
|
|
181
|
-
pingCount: next.pingCount,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
// Different process owns. Coalesce — bump pingCount + push scheduledAt only.
|
|
189
|
-
const next = {
|
|
190
|
-
...existing,
|
|
191
|
-
lastPingAt: opts.now,
|
|
192
|
-
pingCount: existing.pingCount + 1,
|
|
193
|
-
scheduledAt: this.computeScheduledAt(opts, existing),
|
|
194
|
-
};
|
|
195
|
-
try {
|
|
196
|
-
await kv.update(key, JSON.stringify(next), entry?.revision ?? 0);
|
|
197
|
-
return {
|
|
198
|
-
outcome: "coalesce",
|
|
199
|
-
activeRunId: existing.activeRunId,
|
|
200
|
-
scheduledAt: next.scheduledAt,
|
|
201
|
-
pingCount: next.pingCount,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
// CAS conflict — fall through to the next loop iteration.
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
// CAS retries exhausted — over-coalesce: read the current owner and
|
|
209
|
-
// return coalesce. Last-resort fallback that prefers admitting a
|
|
210
|
-
// ping (with attribution to whoever currently owns) over dropping it.
|
|
211
|
-
const entry = await this.safeGet(kv, key);
|
|
212
|
-
if (entry && entry !== "fetch-failed") {
|
|
213
|
-
const existing = this.parseDoc(entry);
|
|
214
|
-
if (existing) {
|
|
215
|
-
return {
|
|
216
|
-
outcome: "coalesce",
|
|
217
|
-
activeRunId: existing.activeRunId,
|
|
218
|
-
scheduledAt: existing.scheduledAt,
|
|
219
|
-
pingCount: existing.pingCount,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
// No doc readable — best-effort owner-new with caller's runId so
|
|
224
|
-
// the coordinator drives a local timer; the next ping will resolve
|
|
225
|
-
// the race.
|
|
226
|
-
return {
|
|
227
|
-
outcome: "owner-new",
|
|
228
|
-
activeRunId: opts.runId,
|
|
229
|
-
scheduledAt: opts.now + opts.delayMs,
|
|
230
|
-
pingCount: 1,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
async finalize(workflowName, debounceKey, runId, now) {
|
|
234
|
-
const kv = this.requireKv();
|
|
235
|
-
const key = this.bucketKey(workflowName, debounceKey);
|
|
236
|
-
for (let attempt = 0; attempt < MAX_CAS_RETRIES; attempt++) {
|
|
237
|
-
const entry = await this.safeGet(kv, key);
|
|
238
|
-
if (entry === "fetch-failed") {
|
|
239
|
-
return { finalize: "abandoned" };
|
|
240
|
-
}
|
|
241
|
-
if (!entry)
|
|
242
|
-
return { finalize: "abandoned" };
|
|
243
|
-
const doc = this.parseDoc(entry);
|
|
244
|
-
if (!doc)
|
|
245
|
-
return { finalize: "abandoned" };
|
|
246
|
-
// Different runId now owns → abandoned (owner lease handed off).
|
|
247
|
-
if (doc.activeRunId !== runId)
|
|
248
|
-
return { finalize: "abandoned" };
|
|
249
|
-
// Coalesce pings pushed scheduledAt forward → reschedule.
|
|
250
|
-
if (now < doc.scheduledAt) {
|
|
251
|
-
return { finalize: "reschedule", scheduledAt: doc.scheduledAt };
|
|
252
|
-
}
|
|
253
|
-
// Same owner + scheduledAt elapsed → try to fire (DELETE).
|
|
254
|
-
try {
|
|
255
|
-
await kv.delete(key);
|
|
256
|
-
return { finalize: "fire" };
|
|
257
|
-
}
|
|
258
|
-
catch {
|
|
259
|
-
// Race — another op modified the bucket; fall through to retry.
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
return { finalize: "abandoned" };
|
|
263
|
-
}
|
|
264
|
-
async cancel(workflowName, debounceKey) {
|
|
265
|
-
const kv = this.requireKv();
|
|
266
|
-
const key = this.bucketKey(workflowName, debounceKey);
|
|
267
|
-
const entry = await this.safeGet(kv, key);
|
|
268
|
-
if (!entry || entry === "fetch-failed")
|
|
269
|
-
return false;
|
|
270
|
-
try {
|
|
271
|
-
await kv.delete(key);
|
|
272
|
-
return true;
|
|
273
|
-
}
|
|
274
|
-
catch {
|
|
275
|
-
return false;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
async purgeExpired(now) {
|
|
279
|
-
const kv = this.requireKv();
|
|
280
|
-
let purged = 0;
|
|
281
|
-
// Drain `kv.keys()` to an array BEFORE doing per-key reads.
|
|
282
|
-
// nats.js v2.x's `QueuedIterator` silently drops yields when
|
|
283
|
-
// `kv.get()` is interleaved with the iteration (the watch's
|
|
284
|
-
// internal consumer gets confused). Collect first, then operate.
|
|
285
|
-
const allKeys = [];
|
|
286
|
-
for await (const key of await kv.keys()) {
|
|
287
|
-
allKeys.push(key);
|
|
288
|
-
}
|
|
289
|
-
for (const key of allKeys) {
|
|
290
|
-
const entry = await this.safeGet(kv, key);
|
|
291
|
-
if (!entry || entry === "fetch-failed")
|
|
292
|
-
continue;
|
|
293
|
-
const doc = this.parseDoc(entry);
|
|
294
|
-
if (!doc)
|
|
295
|
-
continue;
|
|
296
|
-
// Bucket is purgeable when both: owner-lease expired AND
|
|
297
|
-
// scheduledAt elapsed (no active owner with a pending fire).
|
|
298
|
-
if (doc.ownerLeaseExpiresAt <= now && doc.scheduledAt <= now) {
|
|
299
|
-
try {
|
|
300
|
-
await kv.delete(key);
|
|
301
|
-
purged += 1;
|
|
302
|
-
}
|
|
303
|
-
catch {
|
|
304
|
-
// CAS conflict — leave for next sweep.
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return purged;
|
|
309
|
-
}
|
|
310
|
-
async safeGet(kv, key) {
|
|
311
|
-
try {
|
|
312
|
-
const e = await kv.get(key);
|
|
313
|
-
return e ?? null;
|
|
314
|
-
}
|
|
315
|
-
catch (err) {
|
|
316
|
-
const code = err.code;
|
|
317
|
-
if (code === "NotFound" || code === "404")
|
|
318
|
-
return null;
|
|
319
|
-
return "fetch-failed";
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
parseDoc(entry) {
|
|
323
|
-
try {
|
|
324
|
-
const parsed = JSON.parse(entry.string());
|
|
325
|
-
if (!parsed || typeof parsed.activeRunId !== "string")
|
|
326
|
-
return null;
|
|
327
|
-
return parsed;
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
//# sourceMappingURL=NatsKvDebounceBackend.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NatsKvDebounceBackend.js","sourceRoot":"","sources":["../../src/scheduling/NatsKvDebounceBackend.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tier C #1 · Redis-backed debounce backend.
|
|
3
|
-
*
|
|
4
|
-
* Coordinates per-(workflow, debounceKey) window state across processes
|
|
5
|
-
* via a single Redis string key per bucket. Atomicity comes from
|
|
6
|
-
* server-side **Lua scripts** — `registerPing` / `finalize` /
|
|
7
|
-
* `cancel` / `purgeExpired` each run as a single `EVAL` with no OCC
|
|
8
|
-
* retry loop (Lua runs single-threaded against the keyspace).
|
|
9
|
-
*
|
|
10
|
-
* Storage shape: one JSON document per `(workflowName, debounceKey)`
|
|
11
|
-
* bucket. Owner identity is encoded in the doc itself as
|
|
12
|
-
* `(activeRunId, ownerProcessId, ownerLeaseExpiresAt)`; lease handoff
|
|
13
|
-
* happens atomically when a ping arrives after the lease expired.
|
|
14
|
-
*
|
|
15
|
-
* **Owner-local payload**: this backend tracks `pingCount`,
|
|
16
|
-
* `lastPingAt`, and `scheduledAt` only — payloads do NOT travel across
|
|
17
|
-
* processes. The owning process's local `onFire` closure fires when
|
|
18
|
-
* its timer elapses.
|
|
19
|
-
*/
|
|
20
|
-
import type { DebounceBackend, DebounceFinalizeResult, DebounceRegisterBackendOpts, DebounceRegisterBackendResult } from "./DebounceBackend";
|
|
21
|
-
export interface RedisDebounceConfig {
|
|
22
|
-
url?: string;
|
|
23
|
-
host?: string;
|
|
24
|
-
port?: number;
|
|
25
|
-
username?: string;
|
|
26
|
-
password?: string;
|
|
27
|
-
db?: number;
|
|
28
|
-
tls?: boolean;
|
|
29
|
-
keyPrefix: string;
|
|
30
|
-
}
|
|
31
|
-
export declare function readRedisDebounceConfigFromEnv(): RedisDebounceConfig;
|
|
32
|
-
export declare class RedisDebounceBackend implements DebounceBackend {
|
|
33
|
-
readonly name = "redis";
|
|
34
|
-
private client;
|
|
35
|
-
private readonly config;
|
|
36
|
-
private connected;
|
|
37
|
-
constructor(config?: Partial<RedisDebounceConfig>);
|
|
38
|
-
connect(): Promise<void>;
|
|
39
|
-
disconnect(): Promise<void>;
|
|
40
|
-
private bucketKey;
|
|
41
|
-
private encodeSegment;
|
|
42
|
-
private requireClient;
|
|
43
|
-
registerPing(opts: DebounceRegisterBackendOpts): Promise<DebounceRegisterBackendResult>;
|
|
44
|
-
finalize(workflowName: string, debounceKey: string, runId: string, now: number): Promise<DebounceFinalizeResult>;
|
|
45
|
-
cancel(workflowName: string, debounceKey: string): Promise<boolean>;
|
|
46
|
-
purgeExpired(now: number): Promise<number>;
|
|
47
|
-
private parseRegisterResult;
|
|
48
|
-
private parseFinalizeResult;
|
|
49
|
-
}
|