@workflow/world-local 5.0.0-beta.10 → 5.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +17 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -13
- package/dist/config.js.map +1 -1
- package/dist/fs.d.ts +58 -2
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +203 -24
- package/dist/fs.js.map +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -5
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +91 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +268 -0
- package/dist/init.js.map +1 -0
- package/dist/instrumentObject.d.ts +8 -0
- package/dist/instrumentObject.d.ts.map +1 -0
- package/dist/instrumentObject.js +66 -0
- package/dist/instrumentObject.js.map +1 -0
- package/dist/queue.d.ts +8 -1
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +164 -53
- package/dist/queue.js.map +1 -1
- package/dist/storage/events-storage.d.ts +7 -0
- package/dist/storage/events-storage.d.ts.map +1 -0
- package/dist/storage/events-storage.js +744 -0
- package/dist/storage/events-storage.js.map +1 -0
- package/dist/storage/filters.d.ts +22 -0
- package/dist/storage/filters.d.ts.map +1 -0
- package/dist/storage/filters.js +33 -0
- package/dist/storage/filters.js.map +1 -0
- package/dist/storage/helpers.d.ts +18 -0
- package/dist/storage/helpers.d.ts.map +1 -0
- package/dist/storage/helpers.js +44 -0
- package/dist/storage/helpers.js.map +1 -0
- package/dist/storage/hooks-storage.d.ts +12 -0
- package/dist/storage/hooks-storage.d.ts.map +1 -0
- package/dist/storage/hooks-storage.js +92 -0
- package/dist/storage/hooks-storage.js.map +1 -0
- package/dist/storage/index.d.ts +12 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +32 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/legacy.d.ts +13 -0
- package/dist/storage/legacy.d.ts.map +1 -0
- package/dist/storage/legacy.js +73 -0
- package/dist/storage/legacy.js.map +1 -0
- package/dist/storage/runs-storage.d.ts +7 -0
- package/dist/storage/runs-storage.d.ts.map +1 -0
- package/dist/storage/runs-storage.js +58 -0
- package/dist/storage/runs-storage.js.map +1 -0
- package/dist/storage/steps-storage.d.ts +7 -0
- package/dist/storage/steps-storage.d.ts.map +1 -0
- package/dist/storage/steps-storage.js +49 -0
- package/dist/storage/steps-storage.js.map +1 -0
- package/dist/storage.d.ts +9 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +8 -455
- package/dist/storage.js.map +1 -1
- package/dist/streamer.d.ts +4 -2
- package/dist/streamer.d.ts.map +1 -1
- package/dist/streamer.js +451 -104
- package/dist/streamer.js.map +1 -1
- package/dist/telemetry.d.ts +28 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +71 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/test-helpers.d.ts +54 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +118 -0
- package/dist/test-helpers.js.map +1 -0
- package/dist/util.js.map +1 -1
- package/package.json +12 -11
package/dist/queue.js
CHANGED
|
@@ -1,26 +1,80 @@
|
|
|
1
1
|
import { setTimeout } from 'node:timers/promises';
|
|
2
|
-
import { JsonTransport } from '@vercel/queue';
|
|
3
2
|
import { MessageId, ValidQueueName } from '@workflow/world';
|
|
3
|
+
import { Sema } from 'async-sema';
|
|
4
4
|
import { monotonicFactory } from 'ulid';
|
|
5
5
|
import { Agent } from 'undici';
|
|
6
|
-
import z from 'zod';
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
7
|
import { resolveBaseUrl } from './config.js';
|
|
8
|
+
import { jsonReplacer, jsonReviver } from './fs.js';
|
|
9
|
+
import { getPackageInfo } from './init.js';
|
|
10
|
+
/**
|
|
11
|
+
* JSON transport that preserves Uint8Array values using the same
|
|
12
|
+
* replacer/reviver that world-local uses for filesystem storage.
|
|
13
|
+
* Uint8Array → { __type: 'Uint8Array', data: '<base64>' } in JSON.
|
|
14
|
+
*/
|
|
15
|
+
class TypedJsonTransport {
|
|
16
|
+
contentType = 'application/json';
|
|
17
|
+
serialize(value) {
|
|
18
|
+
return Buffer.from(JSON.stringify(value, jsonReplacer));
|
|
19
|
+
}
|
|
20
|
+
async deserialize(stream) {
|
|
21
|
+
const chunks = [];
|
|
22
|
+
const reader = stream.getReader();
|
|
23
|
+
while (true) {
|
|
24
|
+
const { done, value } = await reader.read();
|
|
25
|
+
if (done)
|
|
26
|
+
break;
|
|
27
|
+
if (value)
|
|
28
|
+
chunks.push(value);
|
|
29
|
+
}
|
|
30
|
+
const text = Buffer.concat(chunks).toString();
|
|
31
|
+
return JSON.parse(text, jsonReviver);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
8
34
|
// For local queue, there is no technical limit on the message visibility lifespan,
|
|
9
35
|
// but the environment variable can be used for testing purposes to set a max visibility limit.
|
|
10
36
|
const LOCAL_QUEUE_MAX_VISIBILITY = parseInt(process.env.WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY ?? '0', 10) ||
|
|
11
37
|
Infinity;
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
38
|
+
// Maximum safe delay for setTimeout in Node.js (2^31 - 1 milliseconds ≈ 24.85 days)
|
|
39
|
+
// Larger values cause "TimeoutOverflowWarning: X does not fit into a 32-bit signed integer"
|
|
40
|
+
// When the clamped timeout fires, the handler will recalculate remaining time from
|
|
41
|
+
// persistent state and return another timeoutSeconds if needed.
|
|
42
|
+
const MAX_SAFE_TIMEOUT_MS = 2147483647;
|
|
43
|
+
// The local workers share the same Node.js process and event loop,
|
|
44
|
+
// so we need to limit concurrency to avoid overwhelming the system.
|
|
45
|
+
const DEFAULT_CONCURRENCY_LIMIT = 1000;
|
|
46
|
+
const WORKFLOW_LOCAL_QUEUE_CONCURRENCY = parseInt(process.env.WORKFLOW_LOCAL_QUEUE_CONCURRENCY ?? '0', 10) ||
|
|
47
|
+
DEFAULT_CONCURRENCY_LIMIT;
|
|
48
|
+
function getQueueRoute(queueName) {
|
|
49
|
+
if (queueName.startsWith('__wkf_step_')) {
|
|
50
|
+
return { pathname: 'step', prefix: '__wkf_step_' };
|
|
51
|
+
}
|
|
52
|
+
if (queueName.startsWith('__wkf_workflow_')) {
|
|
53
|
+
return { pathname: 'flow', prefix: '__wkf_workflow_' };
|
|
54
|
+
}
|
|
55
|
+
throw new Error('Unknown queue name prefix');
|
|
56
|
+
}
|
|
16
57
|
export function createQueue(config) {
|
|
17
|
-
|
|
58
|
+
// Create a custom agent optimized for high-concurrency local workflows:
|
|
59
|
+
// - headersTimeout: 0 allows long-running steps
|
|
60
|
+
// - connections: 1000 allows many parallel connections to the same host
|
|
61
|
+
// - pipelining: 1 (default) for HTTP/1.1 compatibility
|
|
62
|
+
// - keepAliveTimeout: 30s keeps connections warm for rapid step execution
|
|
63
|
+
const httpAgent = new Agent({
|
|
64
|
+
headersTimeout: 0,
|
|
65
|
+
connections: 1000,
|
|
66
|
+
keepAliveTimeout: 30_000,
|
|
67
|
+
});
|
|
68
|
+
const transport = new TypedJsonTransport();
|
|
18
69
|
const generateId = monotonicFactory();
|
|
70
|
+
const semaphore = new Sema(WORKFLOW_LOCAL_QUEUE_CONCURRENCY);
|
|
19
71
|
/**
|
|
20
72
|
* holds inflight messages by idempotency key to ensure
|
|
21
73
|
* that we don't queue the same message multiple times
|
|
22
74
|
*/
|
|
23
75
|
const inflightMessages = new Map();
|
|
76
|
+
/** Direct in-process handlers by queue prefix, bypassing HTTP when set. */
|
|
77
|
+
const directHandlers = new Map();
|
|
24
78
|
const queue = async (queueName, message, opts) => {
|
|
25
79
|
const cleanup = [];
|
|
26
80
|
if (opts?.idempotencyKey) {
|
|
@@ -30,17 +84,13 @@ export function createQueue(config) {
|
|
|
30
84
|
}
|
|
31
85
|
}
|
|
32
86
|
const body = transport.serialize(message);
|
|
33
|
-
|
|
34
|
-
if (queueName.startsWith('__wkf_step_')) {
|
|
35
|
-
pathname = `step`;
|
|
36
|
-
}
|
|
37
|
-
else if (queueName.startsWith('__wkf_workflow_')) {
|
|
38
|
-
pathname = `flow`;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
throw new Error('Unknown queue name prefix');
|
|
42
|
-
}
|
|
87
|
+
const { pathname, prefix } = getQueueRoute(queueName);
|
|
43
88
|
const messageId = MessageId.parse(`msg_${generateId()}`);
|
|
89
|
+
// Extract identifiers from the message for structured logging.
|
|
90
|
+
// Workflow messages have `runId`, step messages have `workflowRunId` + `stepId`.
|
|
91
|
+
const msg = message;
|
|
92
|
+
const runId = (msg.runId ?? msg.workflowRunId ?? undefined);
|
|
93
|
+
const stepId = (msg.stepId ?? undefined);
|
|
44
94
|
if (opts?.idempotencyKey) {
|
|
45
95
|
const key = opts.idempotencyKey;
|
|
46
96
|
inflightMessages.set(key, messageId);
|
|
@@ -49,46 +99,96 @@ export function createQueue(config) {
|
|
|
49
99
|
});
|
|
50
100
|
}
|
|
51
101
|
(async () => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
102
|
+
const token = semaphore.tryAcquire();
|
|
103
|
+
if (!token) {
|
|
104
|
+
console.warn(`[world-local]: concurrency limit (${WORKFLOW_LOCAL_QUEUE_CONCURRENCY}) reached, waiting for queue to free up`);
|
|
105
|
+
await semaphore.acquire();
|
|
106
|
+
}
|
|
107
|
+
// Safety limit to prevent infinite loops in the local queue.
|
|
108
|
+
// The actual max delivery enforcement happens in the workflow/step handlers
|
|
109
|
+
// (at MAX_QUEUE_DELIVERIES = 48), so this just needs to be comfortably higher.
|
|
110
|
+
const MAX_LOCAL_SAFETY_LIMIT = 256;
|
|
111
|
+
try {
|
|
112
|
+
for (let attempt = 0; attempt < MAX_LOCAL_SAFETY_LIMIT; attempt++) {
|
|
113
|
+
const headers = {
|
|
114
|
+
...opts?.headers,
|
|
62
115
|
'content-type': 'application/json',
|
|
63
116
|
'x-vqs-queue-name': queueName,
|
|
64
117
|
'x-vqs-message-id': messageId,
|
|
65
118
|
'x-vqs-message-attempt': String(attempt + 1),
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
119
|
+
};
|
|
120
|
+
const directHandler = directHandlers.get(prefix);
|
|
121
|
+
let response;
|
|
122
|
+
if (directHandler) {
|
|
123
|
+
const req = new Request(`http://localhost/.well-known/workflow/v1/${pathname}`, {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
headers,
|
|
126
|
+
body,
|
|
127
|
+
});
|
|
128
|
+
response = await directHandler(req);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const baseUrl = await resolveBaseUrl(config);
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- undici v7 dispatcher types don't match @types/node's RequestInit
|
|
133
|
+
response = await fetch(`${baseUrl}/.well-known/workflow/v1/${pathname}`, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
duplex: 'half',
|
|
136
|
+
dispatcher: httpAgent,
|
|
137
|
+
headers,
|
|
138
|
+
body,
|
|
139
|
+
});
|
|
79
140
|
}
|
|
80
|
-
|
|
141
|
+
const text = await response.text();
|
|
142
|
+
if (response.ok) {
|
|
143
|
+
try {
|
|
144
|
+
const timeoutSeconds = Number(JSON.parse(text).timeoutSeconds);
|
|
145
|
+
if (Number.isFinite(timeoutSeconds) && timeoutSeconds >= 0) {
|
|
146
|
+
// Clamp to MAX_SAFE_TIMEOUT_MS to avoid Node.js setTimeout overflow warning.
|
|
147
|
+
// When this fires early, the handler recalculates remaining time from
|
|
148
|
+
// persistent state and returns another timeoutSeconds if needed.
|
|
149
|
+
if (timeoutSeconds > 0) {
|
|
150
|
+
const timeoutMs = Math.min(timeoutSeconds * 1000, MAX_SAFE_TIMEOUT_MS);
|
|
151
|
+
await setTimeout(timeoutMs);
|
|
152
|
+
}
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { }
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
console.error(`[world-local] Queue message failed (attempt ${attempt + 1}, HTTP ${response.status})`, {
|
|
160
|
+
queueName,
|
|
161
|
+
messageId,
|
|
162
|
+
...(runId && { runId }),
|
|
163
|
+
...(stepId && { stepId }),
|
|
164
|
+
handlerError: text,
|
|
165
|
+
});
|
|
166
|
+
// 5s linear backoff to approximate VQS retry timing in local dev.
|
|
167
|
+
// VQS uses 5s linear for attempts 1–32, then exponential, but for
|
|
168
|
+
// local dev linear 5s is sufficient — the handler enforces the real
|
|
169
|
+
// cap at MAX_QUEUE_DELIVERIES (48) which keeps total time under ~4min.
|
|
170
|
+
await setTimeout(5000);
|
|
81
171
|
}
|
|
82
|
-
console.error(`[
|
|
172
|
+
console.error(`[world-local] Queue message exhausted safety limit (${MAX_LOCAL_SAFETY_LIMIT} attempts)`, {
|
|
83
173
|
queueName,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
body: body.toString(),
|
|
174
|
+
messageId,
|
|
175
|
+
...(runId && { runId }),
|
|
176
|
+
...(stepId && { stepId }),
|
|
88
177
|
});
|
|
89
178
|
}
|
|
90
|
-
|
|
91
|
-
|
|
179
|
+
finally {
|
|
180
|
+
semaphore.release();
|
|
181
|
+
}
|
|
182
|
+
})()
|
|
183
|
+
.catch((err) => {
|
|
184
|
+
// Silently ignore client disconnect errors (e.g., browser refresh during streaming)
|
|
185
|
+
// These are expected and should not cause unhandled rejection warnings
|
|
186
|
+
const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
|
|
187
|
+
if (!isAbortError) {
|
|
188
|
+
console.error('[local world] Queue operation failed:', err);
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
.finally(() => {
|
|
92
192
|
for (const fn of cleanup) {
|
|
93
193
|
fn();
|
|
94
194
|
}
|
|
@@ -116,15 +216,15 @@ export function createQueue(config) {
|
|
|
116
216
|
if (!queueName.startsWith(prefix)) {
|
|
117
217
|
return Response.json({ error: 'Unhandled queue' }, { status: 400 });
|
|
118
218
|
}
|
|
119
|
-
const body = await new
|
|
219
|
+
const body = await new TypedJsonTransport().deserialize(req.body);
|
|
120
220
|
try {
|
|
121
221
|
const result = await handler(body, { attempt, queueName, messageId });
|
|
122
222
|
let timeoutSeconds = null;
|
|
123
223
|
if (typeof result?.timeoutSeconds === 'number') {
|
|
124
224
|
timeoutSeconds = Math.min(result.timeoutSeconds, LOCAL_QUEUE_MAX_VISIBILITY);
|
|
125
225
|
}
|
|
126
|
-
if (timeoutSeconds) {
|
|
127
|
-
return Response.json({ timeoutSeconds }
|
|
226
|
+
if (timeoutSeconds != null) {
|
|
227
|
+
return Response.json({ timeoutSeconds });
|
|
128
228
|
}
|
|
129
229
|
return Response.json({ ok: true });
|
|
130
230
|
}
|
|
@@ -134,8 +234,19 @@ export function createQueue(config) {
|
|
|
134
234
|
};
|
|
135
235
|
};
|
|
136
236
|
const getDeploymentId = async () => {
|
|
137
|
-
|
|
237
|
+
const packageInfo = await getPackageInfo();
|
|
238
|
+
return `dpl_local@${packageInfo.version}`;
|
|
239
|
+
};
|
|
240
|
+
return {
|
|
241
|
+
queue,
|
|
242
|
+
createQueueHandler,
|
|
243
|
+
getDeploymentId,
|
|
244
|
+
registerHandler(prefix, handler) {
|
|
245
|
+
directHandlers.set(prefix, handler);
|
|
246
|
+
},
|
|
247
|
+
async close() {
|
|
248
|
+
await httpAgent.close();
|
|
249
|
+
},
|
|
138
250
|
};
|
|
139
|
-
return { queue, createQueueHandler, getDeploymentId };
|
|
140
251
|
}
|
|
141
252
|
//# sourceMappingURL=queue.js.map
|
package/dist/queue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport type { Transport } from '@vercel/queue';\nimport { MessageId, type Queue, ValidQueueName } from '@workflow/world';\nimport { Sema } from 'async-sema';\nimport { monotonicFactory } from 'ulid';\nimport { Agent } from 'undici';\nimport { z } from 'zod/v4';\nimport type { Config } from './config.js';\nimport { resolveBaseUrl } from './config.js';\nimport { jsonReplacer, jsonReviver } from './fs.js';\nimport { getPackageInfo } from './init.js';\n\n/**\n * JSON transport that preserves Uint8Array values using the same\n * replacer/reviver that world-local uses for filesystem storage.\n * Uint8Array → { __type: 'Uint8Array', data: '<base64>' } in JSON.\n */\nclass TypedJsonTransport implements Transport<unknown> {\n readonly contentType = 'application/json';\n\n serialize(value: unknown): Buffer {\n return Buffer.from(JSON.stringify(value, jsonReplacer));\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<unknown> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n const text = Buffer.concat(chunks).toString();\n return JSON.parse(text, jsonReviver);\n }\n}\n\n// For local queue, there is no technical limit on the message visibility lifespan,\n// but the environment variable can be used for testing purposes to set a max visibility limit.\nconst LOCAL_QUEUE_MAX_VISIBILITY =\n parseInt(process.env.WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY ?? '0', 10) ||\n Infinity;\n\n// Maximum safe delay for setTimeout in Node.js (2^31 - 1 milliseconds ≈ 24.85 days)\n// Larger values cause \"TimeoutOverflowWarning: X does not fit into a 32-bit signed integer\"\n// When the clamped timeout fires, the handler will recalculate remaining time from\n// persistent state and return another timeoutSeconds if needed.\nconst MAX_SAFE_TIMEOUT_MS = 2147483647;\n\n// The local workers share the same Node.js process and event loop,\n// so we need to limit concurrency to avoid overwhelming the system.\nconst DEFAULT_CONCURRENCY_LIMIT = 1000;\nconst WORKFLOW_LOCAL_QUEUE_CONCURRENCY =\n parseInt(process.env.WORKFLOW_LOCAL_QUEUE_CONCURRENCY ?? '0', 10) ||\n DEFAULT_CONCURRENCY_LIMIT;\n\nexport type DirectHandler = (req: Request) => Promise<Response>;\n\nexport type LocalQueue = Queue & {\n /** Close the HTTP agent and release resources. */\n close(): Promise<void>;\n /** Register a direct in-process handler for a queue prefix, bypassing HTTP. */\n registerHandler(\n prefix: '__wkf_step_' | '__wkf_workflow_',\n handler: DirectHandler\n ): void;\n};\n\nfunction getQueueRoute(queueName: ValidQueueName): {\n pathname: 'flow' | 'step';\n prefix: '__wkf_step_' | '__wkf_workflow_';\n} {\n if (queueName.startsWith('__wkf_step_')) {\n return { pathname: 'step', prefix: '__wkf_step_' };\n }\n if (queueName.startsWith('__wkf_workflow_')) {\n return { pathname: 'flow', prefix: '__wkf_workflow_' };\n }\n throw new Error('Unknown queue name prefix');\n}\n\nexport function createQueue(config: Partial<Config>): LocalQueue {\n // Create a custom agent optimized for high-concurrency local workflows:\n // - headersTimeout: 0 allows long-running steps\n // - connections: 1000 allows many parallel connections to the same host\n // - pipelining: 1 (default) for HTTP/1.1 compatibility\n // - keepAliveTimeout: 30s keeps connections warm for rapid step execution\n const httpAgent = new Agent({\n headersTimeout: 0,\n connections: 1000,\n keepAliveTimeout: 30_000,\n });\n const transport = new TypedJsonTransport();\n const generateId = monotonicFactory();\n const semaphore = new Sema(WORKFLOW_LOCAL_QUEUE_CONCURRENCY);\n\n /**\n * holds inflight messages by idempotency key to ensure\n * that we don't queue the same message multiple times\n */\n const inflightMessages = new Map<string, MessageId>();\n /** Direct in-process handlers by queue prefix, bypassing HTTP when set. */\n const directHandlers = new Map<string, DirectHandler>();\n\n const queue: Queue['queue'] = async (queueName, message, opts) => {\n const cleanup = [] as (() => void)[];\n\n if (opts?.idempotencyKey) {\n const existing = inflightMessages.get(opts.idempotencyKey);\n if (existing) {\n return { messageId: existing };\n }\n }\n\n const body = transport.serialize(message);\n const { pathname, prefix } = getQueueRoute(queueName);\n const messageId = MessageId.parse(`msg_${generateId()}`);\n\n // Extract identifiers from the message for structured logging.\n // Workflow messages have `runId`, step messages have `workflowRunId` + `stepId`.\n const msg = message as Record<string, unknown>;\n const runId = (msg.runId ?? msg.workflowRunId ?? undefined) as\n | string\n | undefined;\n const stepId = (msg.stepId ?? undefined) as string | undefined;\n\n if (opts?.idempotencyKey) {\n const key = opts.idempotencyKey;\n inflightMessages.set(key, messageId);\n cleanup.push(() => {\n inflightMessages.delete(key);\n });\n }\n\n (async () => {\n const token = semaphore.tryAcquire();\n if (!token) {\n console.warn(\n `[world-local]: concurrency limit (${WORKFLOW_LOCAL_QUEUE_CONCURRENCY}) reached, waiting for queue to free up`\n );\n await semaphore.acquire();\n }\n // Safety limit to prevent infinite loops in the local queue.\n // The actual max delivery enforcement happens in the workflow/step handlers\n // (at MAX_QUEUE_DELIVERIES = 48), so this just needs to be comfortably higher.\n const MAX_LOCAL_SAFETY_LIMIT = 256;\n try {\n for (let attempt = 0; attempt < MAX_LOCAL_SAFETY_LIMIT; attempt++) {\n const headers: Record<string, string> = {\n ...opts?.headers,\n 'content-type': 'application/json',\n 'x-vqs-queue-name': queueName,\n 'x-vqs-message-id': messageId,\n 'x-vqs-message-attempt': String(attempt + 1),\n };\n const directHandler = directHandlers.get(prefix);\n let response: Response;\n\n if (directHandler) {\n const req = new Request(\n `http://localhost/.well-known/workflow/v1/${pathname}`,\n {\n method: 'POST',\n headers,\n body,\n }\n );\n response = await directHandler(req);\n } else {\n const baseUrl = await resolveBaseUrl(config);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- undici v7 dispatcher types don't match @types/node's RequestInit\n response = await fetch(\n `${baseUrl}/.well-known/workflow/v1/${pathname}`,\n {\n method: 'POST',\n duplex: 'half',\n dispatcher: httpAgent,\n headers,\n body,\n } as any\n );\n }\n\n const text = await response.text();\n\n if (response.ok) {\n try {\n const timeoutSeconds = Number(JSON.parse(text).timeoutSeconds);\n if (Number.isFinite(timeoutSeconds) && timeoutSeconds >= 0) {\n // Clamp to MAX_SAFE_TIMEOUT_MS to avoid Node.js setTimeout overflow warning.\n // When this fires early, the handler recalculates remaining time from\n // persistent state and returns another timeoutSeconds if needed.\n if (timeoutSeconds > 0) {\n const timeoutMs = Math.min(\n timeoutSeconds * 1000,\n MAX_SAFE_TIMEOUT_MS\n );\n await setTimeout(timeoutMs);\n }\n continue;\n }\n } catch {}\n return;\n }\n\n console.error(\n `[world-local] Queue message failed (attempt ${attempt + 1}, HTTP ${response.status})`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n handlerError: text,\n }\n );\n\n // 5s linear backoff to approximate VQS retry timing in local dev.\n // VQS uses 5s linear for attempts 1–32, then exponential, but for\n // local dev linear 5s is sufficient — the handler enforces the real\n // cap at MAX_QUEUE_DELIVERIES (48) which keeps total time under ~4min.\n await setTimeout(5000);\n }\n\n console.error(\n `[world-local] Queue message exhausted safety limit (${MAX_LOCAL_SAFETY_LIMIT} attempts)`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n }\n );\n } finally {\n semaphore.release();\n }\n })()\n .catch((err) => {\n // Silently ignore client disconnect errors (e.g., browser refresh during streaming)\n // These are expected and should not cause unhandled rejection warnings\n const isAbortError =\n err?.name === 'AbortError' || err?.name === 'ResponseAborted';\n if (!isAbortError) {\n console.error('[local world] Queue operation failed:', err);\n }\n })\n .finally(() => {\n for (const fn of cleanup) {\n fn();\n }\n });\n\n return { messageId };\n };\n\n const HeaderParser = z.object({\n 'x-vqs-queue-name': ValidQueueName,\n 'x-vqs-message-id': MessageId,\n 'x-vqs-message-attempt': z.coerce.number(),\n });\n\n const createQueueHandler: Queue['createQueueHandler'] = (prefix, handler) => {\n return async (req) => {\n const headers = HeaderParser.safeParse(Object.fromEntries(req.headers));\n\n if (!headers.success || !req.body) {\n return Response.json(\n {\n error: !req.body\n ? 'Missing request body'\n : 'Missing required headers',\n },\n { status: 400 }\n );\n }\n\n const queueName = headers.data['x-vqs-queue-name'];\n const messageId = headers.data['x-vqs-message-id'];\n const attempt = headers.data['x-vqs-message-attempt'];\n\n if (!queueName.startsWith(prefix)) {\n return Response.json({ error: 'Unhandled queue' }, { status: 400 });\n }\n\n const body = await new TypedJsonTransport().deserialize(req.body);\n try {\n const result = await handler(body, { attempt, queueName, messageId });\n\n let timeoutSeconds: number | null = null;\n if (typeof result?.timeoutSeconds === 'number') {\n timeoutSeconds = Math.min(\n result.timeoutSeconds,\n LOCAL_QUEUE_MAX_VISIBILITY\n );\n }\n\n if (timeoutSeconds != null) {\n return Response.json({ timeoutSeconds });\n }\n\n return Response.json({ ok: true });\n } catch (error) {\n return Response.json(String(error), { status: 500 });\n }\n };\n };\n\n const getDeploymentId: Queue['getDeploymentId'] = async () => {\n const packageInfo = await getPackageInfo();\n return `dpl_local@${packageInfo.version}`;\n };\n\n return {\n queue,\n createQueueHandler,\n getDeploymentId,\n registerHandler(\n prefix: '__wkf_step_' | '__wkf_workflow_',\n handler: DirectHandler\n ) {\n directHandlers.set(prefix, handler);\n },\n async close() {\n await httpAgent.close();\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Storage } from '@workflow/world';
|
|
2
|
+
/**
|
|
3
|
+
* Creates the events storage implementation using the filesystem.
|
|
4
|
+
* Implements the Storage['events'] interface with create, list, and listByCorrelationId operations.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createEventsStorage(basedir: string, tag?: string): Storage['events'];
|
|
7
|
+
//# sourceMappingURL=events-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-storage.d.ts","sourceRoot":"","sources":["../../src/storage/events-storage.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAMV,OAAO,EAGR,MAAM,iBAAiB,CAAC;AAiDzB;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,QAAQ,CAAC,CAi9BnB"}
|