@blokjs/runner 0.2.2 → 0.6.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.js +32 -3
- package/dist/Blok.js.map +1 -1
- package/dist/Configuration.d.ts +59 -5
- package/dist/Configuration.js +366 -96
- package/dist/Configuration.js.map +1 -1
- package/dist/ForEachNode.d.ts +59 -0
- package/dist/ForEachNode.js +522 -0
- package/dist/ForEachNode.js.map +1 -0
- package/dist/LoopMaxIterationsError.d.ts +11 -0
- package/dist/LoopMaxIterationsError.js +18 -0
- package/dist/LoopMaxIterationsError.js.map +1 -0
- package/dist/LoopNode.d.ts +36 -0
- package/dist/LoopNode.js +182 -0
- package/dist/LoopNode.js.map +1 -0
- package/dist/PayloadTooLargeError.d.ts +19 -0
- package/dist/PayloadTooLargeError.js +29 -0
- package/dist/PayloadTooLargeError.js.map +1 -0
- package/dist/RunCancelledError.d.ts +17 -0
- package/dist/RunCancelledError.js +25 -0
- package/dist/RunCancelledError.js.map +1 -0
- package/dist/Runner.d.ts +11 -1
- package/dist/Runner.js +9 -2
- package/dist/Runner.js.map +1 -1
- package/dist/RunnerSteps.js +648 -44
- package/dist/RunnerSteps.js.map +1 -1
- package/dist/RuntimeAdapterNode.d.ts +2 -1
- package/dist/RuntimeAdapterNode.js +2 -2
- package/dist/RuntimeAdapterNode.js.map +1 -1
- package/dist/RuntimeRegistry.d.ts +23 -2
- package/dist/RuntimeRegistry.js +31 -2
- package/dist/RuntimeRegistry.js.map +1 -1
- package/dist/SubworkflowNode.d.ts +181 -0
- package/dist/SubworkflowNode.js +479 -0
- package/dist/SubworkflowNode.js.map +1 -0
- package/dist/SwitchNode.d.ts +37 -0
- package/dist/SwitchNode.js +153 -0
- package/dist/SwitchNode.js.map +1 -0
- package/dist/TriggerBase.d.ts +178 -0
- package/dist/TriggerBase.js +1032 -5
- package/dist/TriggerBase.js.map +1 -1
- package/dist/TryCatchNode.d.ts +32 -0
- package/dist/TryCatchNode.js +207 -0
- package/dist/TryCatchNode.js.map +1 -0
- package/dist/WaitDispatchRequest.d.ts +38 -0
- package/dist/WaitDispatchRequest.js +13 -0
- package/dist/WaitDispatchRequest.js.map +1 -0
- package/dist/WaitNode.d.ts +23 -0
- package/dist/WaitNode.js +26 -0
- package/dist/WaitNode.js.map +1 -0
- package/dist/adapters/grpc/GrpcCodec.js +2 -2
- package/dist/adapters/grpc/GrpcRuntimeAdapter.d.ts +6 -4
- package/dist/adapters/grpc/GrpcRuntimeAdapter.js +6 -4
- package/dist/adapters/grpc/GrpcRuntimeAdapter.js.map +1 -1
- package/dist/adapters/grpc/types.d.ts +7 -5
- package/dist/adapters/grpc/types.js.map +1 -1
- package/dist/adapters/transport.d.ts +12 -41
- package/dist/adapters/transport.js +21 -70
- package/dist/adapters/transport.js.map +1 -1
- package/dist/cache/NodeResultCache.js +7 -0
- package/dist/cache/NodeResultCache.js.map +1 -1
- package/dist/concurrency/ConcurrencyBackend.d.ts +61 -0
- package/dist/concurrency/ConcurrencyBackend.js +20 -0
- package/dist/concurrency/ConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/ConcurrencyLimitError.d.ts +37 -0
- package/dist/concurrency/ConcurrencyLimitError.js +16 -0
- package/dist/concurrency/ConcurrencyLimitError.js.map +1 -0
- package/dist/concurrency/NatsKvConcurrencyBackend.d.ts +64 -0
- package/dist/concurrency/NatsKvConcurrencyBackend.js +310 -0
- package/dist/concurrency/NatsKvConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/QueueExpiredError.d.ts +40 -0
- package/dist/concurrency/QueueExpiredError.js +15 -0
- package/dist/concurrency/QueueExpiredError.js.map +1 -0
- package/dist/concurrency/RedisConcurrencyBackend.d.ts +64 -0
- package/dist/concurrency/RedisConcurrencyBackend.js +374 -0
- package/dist/concurrency/RedisConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/createConcurrencyBackend.d.ts +24 -0
- package/dist/concurrency/createConcurrencyBackend.js +38 -0
- package/dist/concurrency/createConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/readConcurrencyConfig.d.ts +60 -0
- package/dist/concurrency/readConcurrencyConfig.js +60 -0
- package/dist/concurrency/readConcurrencyConfig.js.map +1 -0
- package/dist/defineNode.d.ts +8 -0
- package/dist/defineNode.js +25 -5
- package/dist/defineNode.js.map +1 -1
- package/dist/graphql/GraphQLSchemaGenerator.js +1 -1
- package/dist/graphql/GraphQLSchemaGenerator.js.map +1 -1
- package/dist/idempotency/resolveIdempotencyKey.d.ts +20 -0
- package/dist/idempotency/resolveIdempotencyKey.js +37 -0
- package/dist/idempotency/resolveIdempotencyKey.js.map +1 -0
- package/dist/index.d.ts +30 -6
- package/dist/index.js +55 -6
- package/dist/index.js.map +1 -1
- package/dist/marketplace/RuntimeCatalog.d.ts +6 -0
- package/dist/marketplace/RuntimeCatalog.js.map +1 -1
- package/dist/marketplace/RuntimeDiscovery.d.ts +2 -2
- package/dist/marketplace/RuntimeDiscovery.js +18 -6
- package/dist/marketplace/RuntimeDiscovery.js.map +1 -1
- package/dist/monitoring/ConcurrencyMetrics.d.ts +82 -0
- package/dist/monitoring/ConcurrencyMetrics.js +139 -0
- package/dist/monitoring/ConcurrencyMetrics.js.map +1 -0
- package/dist/monitoring/ForEachWaitMetrics.d.ts +22 -0
- package/dist/monitoring/ForEachWaitMetrics.js +36 -0
- package/dist/monitoring/ForEachWaitMetrics.js.map +1 -0
- package/dist/monitoring/JanitorMetrics.d.ts +27 -0
- package/dist/monitoring/JanitorMetrics.js +48 -0
- package/dist/monitoring/JanitorMetrics.js.map +1 -0
- package/dist/openapi/OpenAPIGenerator.js +7 -2
- package/dist/openapi/OpenAPIGenerator.js.map +1 -1
- package/dist/runtime/PrimitiveStack.d.ts +64 -0
- package/dist/runtime/PrimitiveStack.js +92 -0
- package/dist/runtime/PrimitiveStack.js.map +1 -0
- package/dist/scheduling/DebounceBackend.d.ts +108 -0
- package/dist/scheduling/DebounceBackend.js +23 -0
- package/dist/scheduling/DebounceBackend.js.map +1 -0
- package/dist/scheduling/DebounceCoordinator.d.ts +141 -0
- package/dist/scheduling/DebounceCoordinator.js +362 -0
- package/dist/scheduling/DebounceCoordinator.js.map +1 -0
- package/dist/scheduling/DeferredDispatchSignal.d.ts +50 -0
- package/dist/scheduling/DeferredDispatchSignal.js +14 -0
- package/dist/scheduling/DeferredDispatchSignal.js.map +1 -0
- package/dist/scheduling/DeferredRunScheduler.d.ts +96 -0
- package/dist/scheduling/DeferredRunScheduler.js +256 -0
- package/dist/scheduling/DeferredRunScheduler.js.map +1 -0
- package/dist/scheduling/NatsKvDebounceBackend.d.ts +53 -0
- package/dist/scheduling/NatsKvDebounceBackend.js +334 -0
- package/dist/scheduling/NatsKvDebounceBackend.js.map +1 -0
- package/dist/scheduling/RedisDebounceBackend.d.ts +49 -0
- package/dist/scheduling/RedisDebounceBackend.js +356 -0
- package/dist/scheduling/RedisDebounceBackend.js.map +1 -0
- package/dist/scheduling/createDebounceBackend.d.ts +25 -0
- package/dist/scheduling/createDebounceBackend.js +39 -0
- package/dist/scheduling/createDebounceBackend.js.map +1 -0
- package/dist/scheduling/readSchedulingConfig.d.ts +24 -0
- package/dist/scheduling/readSchedulingConfig.js +52 -0
- package/dist/scheduling/readSchedulingConfig.js.map +1 -0
- package/dist/security/AuditLogger.js +1 -1
- package/dist/security/AuditLogger.js.map +1 -1
- package/dist/security/AuthMiddleware.d.ts +19 -20
- package/dist/security/AuthMiddleware.js +35 -20
- package/dist/security/AuthMiddleware.js.map +1 -1
- package/dist/security/OAuthProvider.js +2 -2
- package/dist/security/OAuthProvider.js.map +1 -1
- package/dist/security/SecretManager.js +14 -13
- package/dist/security/SecretManager.js.map +1 -1
- package/dist/security/index.d.ts +3 -1
- package/dist/security/index.js +3 -1
- package/dist/security/index.js.map +1 -1
- package/dist/testing/TestHarness.d.ts +27 -12
- package/dist/testing/TestHarness.js +19 -3
- package/dist/testing/TestHarness.js.map +1 -1
- package/dist/testing/WorkflowTestRunner.js +0 -7
- package/dist/testing/WorkflowTestRunner.js.map +1 -1
- package/dist/timeouts/StepTimeoutError.d.ts +22 -0
- package/dist/timeouts/StepTimeoutError.js +31 -0
- package/dist/timeouts/StepTimeoutError.js.map +1 -0
- package/dist/tracing/InMemoryRunStore.d.ts +41 -1
- package/dist/tracing/InMemoryRunStore.js +239 -0
- package/dist/tracing/InMemoryRunStore.js.map +1 -1
- package/dist/tracing/Janitor.d.ts +70 -0
- package/dist/tracing/Janitor.js +150 -0
- package/dist/tracing/Janitor.js.map +1 -0
- package/dist/tracing/PostgresRunStore.d.ts +57 -1
- package/dist/tracing/PostgresRunStore.js +711 -6
- package/dist/tracing/PostgresRunStore.js.map +1 -1
- package/dist/tracing/RoutingDiagnostics.d.ts +55 -0
- package/dist/tracing/RoutingDiagnostics.js +50 -0
- package/dist/tracing/RoutingDiagnostics.js.map +1 -0
- package/dist/tracing/RunStore.d.ts +181 -1
- package/dist/tracing/RunTracker.d.ts +244 -9
- package/dist/tracing/RunTracker.js +594 -1
- package/dist/tracing/RunTracker.js.map +1 -1
- package/dist/tracing/SqliteRunStore.d.ts +79 -2
- package/dist/tracing/SqliteRunStore.js +775 -16
- package/dist/tracing/SqliteRunStore.js.map +1 -1
- package/dist/tracing/TraceRouter.d.ts +20 -2
- package/dist/tracing/TraceRouter.js +612 -6
- package/dist/tracing/TraceRouter.js.map +1 -1
- package/dist/tracing/createStore.js +14 -3
- package/dist/tracing/createStore.js.map +1 -1
- package/dist/tracing/metadataFilter.d.ts +63 -0
- package/dist/tracing/metadataFilter.js +224 -0
- package/dist/tracing/metadataFilter.js.map +1 -0
- package/dist/tracing/sanitize.d.ts +11 -0
- package/dist/tracing/sanitize.js +29 -0
- package/dist/tracing/sanitize.js.map +1 -1
- package/dist/tracing/types.d.ts +672 -2
- package/dist/utils/createChildContext.d.ts +32 -0
- package/dist/utils/createChildContext.js +113 -0
- package/dist/utils/createChildContext.js.map +1 -0
- package/dist/utils/envAllowlist.d.ts +35 -0
- package/dist/utils/envAllowlist.js +113 -0
- package/dist/utils/envAllowlist.js.map +1 -0
- package/dist/version/RuntimeVersionValidator.d.ts +38 -0
- package/dist/version/RuntimeVersionValidator.js +121 -0
- package/dist/version/RuntimeVersionValidator.js.map +1 -0
- package/dist/visualization/WorkflowVisualizer.js +4 -4
- package/dist/visualization/WorkflowVisualizer.js.map +1 -1
- package/dist/workflow/PersistenceHelper.d.ts +18 -10
- package/dist/workflow/PersistenceHelper.js +35 -9
- package/dist/workflow/PersistenceHelper.js.map +1 -1
- package/dist/workflow/WorkflowNormalizer.d.ts +48 -42
- package/dist/workflow/WorkflowNormalizer.js +650 -18
- package/dist/workflow/WorkflowNormalizer.js.map +1 -1
- package/dist/workflow/WorkflowRegistry.d.ts +186 -0
- package/dist/workflow/WorkflowRegistry.js +202 -0
- package/dist/workflow/WorkflowRegistry.js.map +1 -0
- package/dist/workflow/sampleBody.d.ts +54 -0
- package/dist/workflow/sampleBody.js +320 -0
- package/dist/workflow/sampleBody.js.map +1 -0
- package/package.json +3 -8
- package/dist/adapters/HttpRuntimeAdapter.d.ts +0 -79
- package/dist/adapters/HttpRuntimeAdapter.js +0 -233
- package/dist/adapters/HttpRuntimeAdapter.js.map +0 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 2 follow-up · periodic janitor sweep for stale storage rows.
|
|
3
|
+
*
|
|
4
|
+
* Background task that runs on a configurable interval (default 5 min,
|
|
5
|
+
* override via `BLOK_JANITOR_INTERVAL_MS`) and invokes the existing
|
|
6
|
+
* lazy-purge methods to clean up:
|
|
7
|
+
*
|
|
8
|
+
* - `idempotency_cache` — entries past `expires_at`
|
|
9
|
+
* - `concurrency_locks` — leases past `expires_at`
|
|
10
|
+
* - `scheduled_dispatches` — rows past `expires_at` (Tier 2 #5+#7 follow-up)
|
|
11
|
+
*
|
|
12
|
+
* Each store's per-call lazy-purge handles the hot path (e.g.,
|
|
13
|
+
* `acquireConcurrencySlot` purges the bucket it touches). The janitor
|
|
14
|
+
* catches stale entries in cold buckets that nothing else accesses.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent + interval-bounded — runs every `intervalMs`; concurrent
|
|
17
|
+
* `runOnce()` calls are serialized via the `inFlight` flag to prevent
|
|
18
|
+
* overlapping sweeps under slow stores. Errors per sweep are caught
|
|
19
|
+
* and logged; one failing sweep doesn't stop the loop or block others.
|
|
20
|
+
*
|
|
21
|
+
* Kill-switch: `BLOK_JANITOR_DISABLED=1`.
|
|
22
|
+
*/
|
|
23
|
+
import type { RunStore } from "./RunStore";
|
|
24
|
+
interface JanitorLogger {
|
|
25
|
+
error?: (message: string) => void;
|
|
26
|
+
log?: (message: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface JanitorStats {
|
|
29
|
+
idempotencyCachePurged: number;
|
|
30
|
+
concurrencySlotsPurged: number;
|
|
31
|
+
scheduledDispatchesPurged: number;
|
|
32
|
+
durationMs: number;
|
|
33
|
+
}
|
|
34
|
+
export declare class Janitor {
|
|
35
|
+
private static instance;
|
|
36
|
+
private readonly store;
|
|
37
|
+
private readonly logger?;
|
|
38
|
+
private timer;
|
|
39
|
+
private inFlight;
|
|
40
|
+
private stopped;
|
|
41
|
+
private constructor();
|
|
42
|
+
/**
|
|
43
|
+
* Get or initialize the singleton. The first call wins — subsequent
|
|
44
|
+
* calls return the existing instance regardless of arguments.
|
|
45
|
+
*/
|
|
46
|
+
static getInstance(store: RunStore, logger?: JanitorLogger): Janitor;
|
|
47
|
+
/** Test-only — reset the singleton. Stops any running interval. */
|
|
48
|
+
static resetInstance(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Start the periodic sweep. Idempotent — calling twice is a no-op.
|
|
51
|
+
* Returns false when the kill-switch is set or the janitor was
|
|
52
|
+
* already started.
|
|
53
|
+
*/
|
|
54
|
+
start(intervalMs?: number): boolean;
|
|
55
|
+
/** Stop the periodic sweep. Idempotent. */
|
|
56
|
+
stop(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Run one sweep immediately. Useful for tests + as a manual janitor
|
|
59
|
+
* command. Concurrent invocations are serialized via the `inFlight`
|
|
60
|
+
* flag — overlapping calls return the same in-progress sweep's stats
|
|
61
|
+
* via the resolved promise.
|
|
62
|
+
*
|
|
63
|
+
* Errors per individual purge method are caught + logged; one failing
|
|
64
|
+
* purge doesn't abort the others.
|
|
65
|
+
*/
|
|
66
|
+
runOnce(): Promise<JanitorStats>;
|
|
67
|
+
/** Whether the janitor is currently running on its interval. */
|
|
68
|
+
isRunning(): boolean;
|
|
69
|
+
}
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 2 follow-up · periodic janitor sweep for stale storage rows.
|
|
3
|
+
*
|
|
4
|
+
* Background task that runs on a configurable interval (default 5 min,
|
|
5
|
+
* override via `BLOK_JANITOR_INTERVAL_MS`) and invokes the existing
|
|
6
|
+
* lazy-purge methods to clean up:
|
|
7
|
+
*
|
|
8
|
+
* - `idempotency_cache` — entries past `expires_at`
|
|
9
|
+
* - `concurrency_locks` — leases past `expires_at`
|
|
10
|
+
* - `scheduled_dispatches` — rows past `expires_at` (Tier 2 #5+#7 follow-up)
|
|
11
|
+
*
|
|
12
|
+
* Each store's per-call lazy-purge handles the hot path (e.g.,
|
|
13
|
+
* `acquireConcurrencySlot` purges the bucket it touches). The janitor
|
|
14
|
+
* catches stale entries in cold buckets that nothing else accesses.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent + interval-bounded — runs every `intervalMs`; concurrent
|
|
17
|
+
* `runOnce()` calls are serialized via the `inFlight` flag to prevent
|
|
18
|
+
* overlapping sweeps under slow stores. Errors per sweep are caught
|
|
19
|
+
* and logged; one failing sweep doesn't stop the loop or block others.
|
|
20
|
+
*
|
|
21
|
+
* Kill-switch: `BLOK_JANITOR_DISABLED=1`.
|
|
22
|
+
*/
|
|
23
|
+
import { JanitorMetrics } from "../monitoring/JanitorMetrics";
|
|
24
|
+
const DEFAULT_INTERVAL_MS = 5 * 60 * 1000;
|
|
25
|
+
export class Janitor {
|
|
26
|
+
static instance = null;
|
|
27
|
+
store;
|
|
28
|
+
logger;
|
|
29
|
+
timer = null;
|
|
30
|
+
inFlight = false;
|
|
31
|
+
stopped = false;
|
|
32
|
+
constructor(store, logger) {
|
|
33
|
+
this.store = store;
|
|
34
|
+
this.logger = logger;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get or initialize the singleton. The first call wins — subsequent
|
|
38
|
+
* calls return the existing instance regardless of arguments.
|
|
39
|
+
*/
|
|
40
|
+
static getInstance(store, logger) {
|
|
41
|
+
if (!Janitor.instance) {
|
|
42
|
+
Janitor.instance = new Janitor(store, logger);
|
|
43
|
+
}
|
|
44
|
+
return Janitor.instance;
|
|
45
|
+
}
|
|
46
|
+
/** Test-only — reset the singleton. Stops any running interval. */
|
|
47
|
+
static resetInstance() {
|
|
48
|
+
Janitor.instance?.stop();
|
|
49
|
+
Janitor.instance = null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Start the periodic sweep. Idempotent — calling twice is a no-op.
|
|
53
|
+
* Returns false when the kill-switch is set or the janitor was
|
|
54
|
+
* already started.
|
|
55
|
+
*/
|
|
56
|
+
start(intervalMs) {
|
|
57
|
+
if (process.env.BLOK_JANITOR_DISABLED === "1")
|
|
58
|
+
return false;
|
|
59
|
+
if (this.timer !== null)
|
|
60
|
+
return false;
|
|
61
|
+
this.stopped = false;
|
|
62
|
+
const envIntervalRaw = process.env.BLOK_JANITOR_INTERVAL_MS;
|
|
63
|
+
const envInterval = envIntervalRaw && /^\d+$/.test(envIntervalRaw) ? Number(envIntervalRaw) : null;
|
|
64
|
+
const interval = intervalMs ?? envInterval ?? DEFAULT_INTERVAL_MS;
|
|
65
|
+
// `unref()` so the janitor doesn't keep the event loop alive on
|
|
66
|
+
// its own — when all triggers shut down, the process should exit.
|
|
67
|
+
this.timer = setInterval(() => {
|
|
68
|
+
void this.runOnce();
|
|
69
|
+
}, interval);
|
|
70
|
+
this.timer.unref?.();
|
|
71
|
+
this.logger?.log?.(`[blok][janitor] started — interval=${interval}ms`);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
/** Stop the periodic sweep. Idempotent. */
|
|
75
|
+
stop() {
|
|
76
|
+
this.stopped = true;
|
|
77
|
+
if (this.timer !== null) {
|
|
78
|
+
clearInterval(this.timer);
|
|
79
|
+
this.timer = null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Run one sweep immediately. Useful for tests + as a manual janitor
|
|
84
|
+
* command. Concurrent invocations are serialized via the `inFlight`
|
|
85
|
+
* flag — overlapping calls return the same in-progress sweep's stats
|
|
86
|
+
* via the resolved promise.
|
|
87
|
+
*
|
|
88
|
+
* Errors per individual purge method are caught + logged; one failing
|
|
89
|
+
* purge doesn't abort the others.
|
|
90
|
+
*/
|
|
91
|
+
async runOnce() {
|
|
92
|
+
if (this.stopped) {
|
|
93
|
+
return { idempotencyCachePurged: 0, concurrencySlotsPurged: 0, scheduledDispatchesPurged: 0, durationMs: 0 };
|
|
94
|
+
}
|
|
95
|
+
if (this.inFlight) {
|
|
96
|
+
// Skip overlapping invocations — return zero stats so callers
|
|
97
|
+
// don't wait on a sweep that's already running.
|
|
98
|
+
return { idempotencyCachePurged: 0, concurrencySlotsPurged: 0, scheduledDispatchesPurged: 0, durationMs: 0 };
|
|
99
|
+
}
|
|
100
|
+
this.inFlight = true;
|
|
101
|
+
const start = Date.now();
|
|
102
|
+
const stats = {
|
|
103
|
+
idempotencyCachePurged: 0,
|
|
104
|
+
concurrencySlotsPurged: 0,
|
|
105
|
+
scheduledDispatchesPurged: 0,
|
|
106
|
+
durationMs: 0,
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
// PR 3 D3 — record per-table duration + rows purged via OTel.
|
|
110
|
+
const idemStart = Date.now();
|
|
111
|
+
try {
|
|
112
|
+
stats.idempotencyCachePurged = this.store.purgeExpiredIdempotencyCache(start);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.logger?.error?.(`[blok][janitor] purgeExpiredIdempotencyCache failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
116
|
+
}
|
|
117
|
+
JanitorMetrics.getInstance().recordSweep({ table: "idempotency_cache" }, Date.now() - idemStart, stats.idempotencyCachePurged);
|
|
118
|
+
const locksStart = Date.now();
|
|
119
|
+
try {
|
|
120
|
+
stats.concurrencySlotsPurged = this.store.purgeExpiredConcurrencySlots(start);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
this.logger?.error?.(`[blok][janitor] purgeExpiredConcurrencySlots failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
124
|
+
}
|
|
125
|
+
JanitorMetrics.getInstance().recordSweep({ table: "concurrency_locks" }, Date.now() - locksStart, stats.concurrencySlotsPurged);
|
|
126
|
+
const dispStart = Date.now();
|
|
127
|
+
try {
|
|
128
|
+
stats.scheduledDispatchesPurged = this.store.purgeExpiredScheduledDispatches(start);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
this.logger?.error?.(`[blok][janitor] purgeExpiredScheduledDispatches failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
132
|
+
}
|
|
133
|
+
JanitorMetrics.getInstance().recordSweep({ table: "scheduled_dispatches" }, Date.now() - dispStart, stats.scheduledDispatchesPurged);
|
|
134
|
+
stats.durationMs = Date.now() - start;
|
|
135
|
+
const totalPurged = stats.idempotencyCachePurged + stats.concurrencySlotsPurged + stats.scheduledDispatchesPurged;
|
|
136
|
+
if (totalPurged > 0) {
|
|
137
|
+
this.logger?.log?.(`[blok][janitor] sweep done — idem=${stats.idempotencyCachePurged} locks=${stats.concurrencySlotsPurged} dispatches=${stats.scheduledDispatchesPurged} (${stats.durationMs}ms)`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
this.inFlight = false;
|
|
142
|
+
}
|
|
143
|
+
return stats;
|
|
144
|
+
}
|
|
145
|
+
/** Whether the janitor is currently running on its interval. */
|
|
146
|
+
isRunning() {
|
|
147
|
+
return this.timer !== null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=Janitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Janitor.js","sourceRoot":"","sources":["../../src/tracing/Janitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RunStore } from "./RunStore";
|
|
2
|
-
import type { Dashboard, MetricsResult, NodeRun, RunEvent, RunQuery, TraceLogEntry, WorkflowRun, WorkflowSummary } from "./types";
|
|
2
|
+
import type { Dashboard, MetricsResult, NodeRun, RunEvent, RunQuery, SavedFilter, ScheduledDispatchRow, TraceLogEntry, WorkflowRun, WorkflowSample, WorkflowSummary } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* PostgreSQL connection configuration.
|
|
5
5
|
*/
|
|
@@ -41,6 +41,14 @@ export declare class PostgresRunStore implements RunStore {
|
|
|
41
41
|
ready(): Promise<void>;
|
|
42
42
|
private initialize;
|
|
43
43
|
private migrate;
|
|
44
|
+
/**
|
|
45
|
+
* Review fix-up · CONCERN-2. Per-table cap on `loadRecent`'s rehydration
|
|
46
|
+
* queries. Without it, a deployment with 1M+ idempotency cache entries
|
|
47
|
+
* spends seconds + memory on every boot loading rows it'll never read
|
|
48
|
+
* before the Janitor sweeps them. Default 100K rows per table — well
|
|
49
|
+
* above any reasonable hot-set size yet bounded for boot latency.
|
|
50
|
+
*/
|
|
51
|
+
private getLoadRecentLimit;
|
|
44
52
|
private loadRecent;
|
|
45
53
|
saveRun(run: WorkflowRun): void;
|
|
46
54
|
updateRun(runId: string, updates: Partial<WorkflowRun>): void;
|
|
@@ -55,6 +63,7 @@ export declare class PostgresRunStore implements RunStore {
|
|
|
55
63
|
};
|
|
56
64
|
getNodeRuns(runId: string): NodeRun[];
|
|
57
65
|
getNodeRun(nodeRunId: string): NodeRun | undefined;
|
|
66
|
+
getRunsByParent(parentRunId: string): WorkflowRun[];
|
|
58
67
|
getEvents(runId: string, since?: number): RunEvent[];
|
|
59
68
|
getLogs(runId: string, nodeId?: string): TraceLogEntry[];
|
|
60
69
|
getWorkflowSummaries(): WorkflowSummary[];
|
|
@@ -66,10 +75,57 @@ export declare class PostgresRunStore implements RunStore {
|
|
|
66
75
|
listDashboards(): Dashboard[];
|
|
67
76
|
deleteDashboard(dashboardId: string): boolean;
|
|
68
77
|
updateDashboard(dashboardId: string, updates: Partial<Dashboard>): void;
|
|
78
|
+
upsertSavedFilter(filter: SavedFilter): SavedFilter;
|
|
79
|
+
listSavedFilters(): SavedFilter[];
|
|
80
|
+
deleteSavedFilter(name: string): boolean;
|
|
81
|
+
recordWorkflowSample(sample: WorkflowSample): WorkflowSample;
|
|
82
|
+
getWorkflowSample(workflowName: string): WorkflowSample | undefined;
|
|
83
|
+
deleteWorkflowSample(workflowName: string): boolean;
|
|
69
84
|
clearAll(): number;
|
|
70
85
|
deleteRunsBefore(timestamp: number): number;
|
|
71
86
|
evictOldRuns(maxRuns: number): void;
|
|
72
87
|
close(): void;
|
|
88
|
+
getIdempotencyCache(workflowName: string, stepId: string, key: string): import("./types").CachedStepResult | null;
|
|
89
|
+
setIdempotencyCache(workflowName: string, stepId: string, key: string, entry: Parameters<typeof this.memory.setIdempotencyCache>[3]): void;
|
|
90
|
+
purgeExpiredIdempotencyCache(now: number): number;
|
|
91
|
+
acquireConcurrencySlot(workflowName: string, concurrencyKey: string, concurrencyLimit: number, runId: string, leaseExpiresAt: number): import("./types").ConcurrencySlotResult;
|
|
92
|
+
releaseConcurrencySlot(workflowName: string, concurrencyKey: string, runId: string): void;
|
|
93
|
+
purgeExpiredConcurrencySlots(now: number): number;
|
|
94
|
+
getConcurrencySnapshot(now: number): {
|
|
95
|
+
workflowName: string;
|
|
96
|
+
concurrencyKey: string;
|
|
97
|
+
leases: Array<{
|
|
98
|
+
runId: string;
|
|
99
|
+
expiresAt: number;
|
|
100
|
+
}>;
|
|
101
|
+
}[];
|
|
102
|
+
upsertScheduledDispatch(row: Parameters<typeof this.memory.upsertScheduledDispatch>[0]): void;
|
|
103
|
+
claimDispatchesAsync(processId: string, leaseMs: number, now: number, opts?: {
|
|
104
|
+
triggerType?: string;
|
|
105
|
+
}): Promise<ScheduledDispatchRow[]>;
|
|
106
|
+
/**
|
|
107
|
+
* Sync wrapper required by the `RunStore` interface. PG's claim API
|
|
108
|
+
* is fundamentally async (network round-trip); the sync wrapper
|
|
109
|
+
* returns the LAST snapshot from the in-memory mirror.
|
|
110
|
+
*
|
|
111
|
+
* **For cross-process correctness, callers MUST use
|
|
112
|
+
* `claimDispatchesAsync()` directly.** The sync wrapper exists so
|
|
113
|
+
* the interface contract is satisfied for sqlite + in-memory
|
|
114
|
+
* callers; PG users opt into the async path via the trigger's
|
|
115
|
+
* recovery code (`HttpTrigger.recoverDispatches()` calls the
|
|
116
|
+
* async version when the store is a `PostgresRunStore`).
|
|
117
|
+
*/
|
|
118
|
+
claimDispatches(processId: string, leaseMs: number, now: number, opts?: {
|
|
119
|
+
triggerType?: string;
|
|
120
|
+
}): ScheduledDispatchRow[];
|
|
121
|
+
heartbeatClaims(processId: string, now: number): number;
|
|
122
|
+
releaseClaim(runId: string): boolean;
|
|
123
|
+
deleteScheduledDispatch(runId: string): boolean;
|
|
124
|
+
getScheduledDispatches(opts?: {
|
|
125
|
+
triggerType?: string;
|
|
126
|
+
status?: string;
|
|
127
|
+
}): ScheduledDispatchRow[];
|
|
128
|
+
purgeExpiredScheduledDispatches(now: number): number;
|
|
73
129
|
private enqueueWrite;
|
|
74
130
|
private flush;
|
|
75
131
|
private startFlushLoop;
|