@upstash/workflow 0.2.8 → 0.2.10-hono-generics
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/astro.d.mts +8 -3
- package/astro.d.ts +8 -3
- package/astro.js +393 -82
- package/astro.mjs +36 -8
- package/{chunk-BPUSHNSD.mjs → chunk-IPXJZU3K.mjs} +1226 -943
- package/cloudflare.d.mts +9 -4
- package/cloudflare.d.ts +9 -4
- package/cloudflare.js +392 -88
- package/cloudflare.mjs +35 -14
- package/express.d.mts +7 -3
- package/express.d.ts +7 -3
- package/express.js +400 -92
- package/express.mjs +43 -18
- package/h3.d.mts +9 -7
- package/h3.d.ts +9 -7
- package/h3.js +397 -95
- package/h3.mjs +40 -21
- package/hono.d.mts +10 -4
- package/hono.d.ts +10 -4
- package/hono.js +391 -90
- package/hono.mjs +34 -16
- package/index.d.mts +47 -33
- package/index.d.ts +47 -33
- package/index.js +315 -92
- package/index.mjs +32 -30
- package/nextjs.d.mts +14 -5
- package/nextjs.d.ts +14 -5
- package/nextjs.js +408 -77
- package/nextjs.mjs +63 -17
- package/package.json +1 -1
- package/serve-many-BVDpPsF-.d.mts +13 -0
- package/serve-many-e4zufyXN.d.ts +13 -0
- package/solidjs.d.mts +3 -3
- package/solidjs.d.ts +3 -3
- package/solidjs.js +289 -71
- package/solidjs.mjs +7 -10
- package/svelte.d.mts +13 -6
- package/svelte.d.ts +13 -6
- package/svelte.js +391 -88
- package/svelte.mjs +34 -14
- package/{types-B62AnIU3.d.mts → types-CYhDXnf8.d.mts} +74 -8
- package/{types-B62AnIU3.d.ts → types-CYhDXnf8.d.ts} +74 -8
|
@@ -36,12 +36,13 @@ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
|
|
|
36
36
|
var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
37
37
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
38
38
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
39
|
+
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
39
40
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
40
41
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
41
42
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
42
43
|
var NO_CONCURRENCY = 1;
|
|
43
44
|
var DEFAULT_RETRIES = 3;
|
|
44
|
-
var VERSION = "v0.2.
|
|
45
|
+
var VERSION = "v0.2.7";
|
|
45
46
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
46
47
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
47
48
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -96,410 +97,71 @@ var StepTypes = [
|
|
|
96
97
|
"SleepUntil",
|
|
97
98
|
"Call",
|
|
98
99
|
"Wait",
|
|
99
|
-
"Notify"
|
|
100
|
+
"Notify",
|
|
101
|
+
"Invoke"
|
|
100
102
|
];
|
|
101
103
|
|
|
102
|
-
// src/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
baseURL,
|
|
125
|
-
apiKey,
|
|
126
|
-
compatibility: "strict",
|
|
127
|
-
fetch: async (input, init) => {
|
|
128
|
-
try {
|
|
129
|
-
const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
|
|
130
|
-
const body = init?.body ? JSON.parse(init.body) : void 0;
|
|
131
|
-
const agentName = headers[AGENT_NAME_HEADER];
|
|
132
|
-
const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
|
|
133
|
-
const responseInfo = await context.call(stepName, {
|
|
134
|
-
url: input.toString(),
|
|
135
|
-
method: init?.method,
|
|
136
|
-
headers,
|
|
137
|
-
body
|
|
138
|
-
});
|
|
139
|
-
const responseHeaders = new Headers(
|
|
140
|
-
Object.entries(responseInfo.header).reduce(
|
|
141
|
-
(acc, [key, values]) => {
|
|
142
|
-
acc[key] = values.join(", ");
|
|
143
|
-
return acc;
|
|
144
|
-
},
|
|
145
|
-
{}
|
|
146
|
-
)
|
|
147
|
-
);
|
|
148
|
-
return new Response(JSON.stringify(responseInfo.body), {
|
|
149
|
-
status: responseInfo.status,
|
|
150
|
-
headers: responseHeaders
|
|
151
|
-
});
|
|
152
|
-
} catch (error) {
|
|
153
|
-
if (error instanceof Error && error.name === "WorkflowAbort") {
|
|
154
|
-
throw error;
|
|
155
|
-
} else {
|
|
156
|
-
console.error("Error in fetch implementation:", error);
|
|
157
|
-
throw error;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
var wrapTools = ({
|
|
164
|
-
context,
|
|
165
|
-
tools
|
|
166
|
-
}) => {
|
|
167
|
-
return Object.fromEntries(
|
|
168
|
-
Object.entries(tools).map((toolInfo) => {
|
|
169
|
-
const [toolName, tool3] = toolInfo;
|
|
170
|
-
const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
|
|
171
|
-
const aiSDKTool = convertToAISDKTool(tool3);
|
|
172
|
-
const execute = aiSDKTool.execute;
|
|
173
|
-
if (execute && executeAsStep) {
|
|
174
|
-
const wrappedExecute = (...params) => {
|
|
175
|
-
return context.run(`Run tool ${toolName}`, () => execute(...params));
|
|
176
|
-
};
|
|
177
|
-
aiSDKTool.execute = wrappedExecute;
|
|
178
|
-
}
|
|
179
|
-
return [toolName, aiSDKTool];
|
|
180
|
-
})
|
|
181
|
-
);
|
|
182
|
-
};
|
|
183
|
-
var convertToAISDKTool = (tool3) => {
|
|
184
|
-
const isLangchainTool = "invoke" in tool3;
|
|
185
|
-
return isLangchainTool ? convertLangchainTool(tool3) : tool3;
|
|
186
|
-
};
|
|
187
|
-
var convertLangchainTool = (langchainTool) => {
|
|
188
|
-
return tool({
|
|
189
|
-
description: langchainTool.description,
|
|
190
|
-
parameters: langchainTool.schema,
|
|
191
|
-
execute: async (...param) => langchainTool.invoke(...param)
|
|
192
|
-
});
|
|
193
|
-
};
|
|
194
|
-
var WorkflowTool = class {
|
|
195
|
-
/**
|
|
196
|
-
* description of the tool
|
|
197
|
-
*/
|
|
198
|
-
description;
|
|
199
|
-
/**
|
|
200
|
-
* schema of the tool
|
|
201
|
-
*/
|
|
202
|
-
schema;
|
|
203
|
-
/**
|
|
204
|
-
* function to invoke the tool
|
|
205
|
-
*/
|
|
206
|
-
invoke;
|
|
207
|
-
/**
|
|
208
|
-
* whether the invoke method of the tool is to be wrapped with `context.run`
|
|
209
|
-
*/
|
|
210
|
-
executeAsStep;
|
|
211
|
-
/**
|
|
212
|
-
*
|
|
213
|
-
* @param description description of the tool
|
|
214
|
-
* @param schema schema of the tool
|
|
215
|
-
* @param invoke function to invoke the tool
|
|
216
|
-
* @param executeAsStep whether the invoke method of the tool is to be wrapped with `context.run`
|
|
217
|
-
*/
|
|
218
|
-
constructor(params) {
|
|
219
|
-
this.description = params.description;
|
|
220
|
-
this.schema = params.schema;
|
|
221
|
-
this.invoke = params.invoke;
|
|
222
|
-
this.executeAsStep = params.executeAsStep ?? true;
|
|
104
|
+
// src/utils.ts
|
|
105
|
+
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
106
|
+
var NANOID_LENGTH = 21;
|
|
107
|
+
function getRandomInt() {
|
|
108
|
+
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
109
|
+
}
|
|
110
|
+
function nanoid() {
|
|
111
|
+
return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
|
|
112
|
+
}
|
|
113
|
+
function getWorkflowRunId(id) {
|
|
114
|
+
return `wfr_${id ?? nanoid()}`;
|
|
115
|
+
}
|
|
116
|
+
function decodeBase64(base64) {
|
|
117
|
+
try {
|
|
118
|
+
const binString = atob(base64);
|
|
119
|
+
const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
120
|
+
return new TextDecoder().decode(intArray);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.warn(
|
|
123
|
+
`Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
|
|
124
|
+
);
|
|
125
|
+
return atob(base64);
|
|
223
126
|
}
|
|
224
|
-
}
|
|
127
|
+
}
|
|
225
128
|
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const result = await requester.request({
|
|
230
|
-
path: ["v2", "notify", eventId],
|
|
231
|
-
method: "POST",
|
|
232
|
-
body: typeof eventData === "string" ? eventData : JSON.stringify(eventData)
|
|
233
|
-
});
|
|
234
|
-
return result;
|
|
235
|
-
};
|
|
236
|
-
var makeGetWaitersRequest = async (requester, eventId) => {
|
|
237
|
-
const result = await requester.request({
|
|
238
|
-
path: ["v2", "waiters", eventId],
|
|
239
|
-
method: "GET"
|
|
240
|
-
});
|
|
241
|
-
return result;
|
|
129
|
+
// node_modules/neverthrow/dist/index.es.js
|
|
130
|
+
var defaultErrorConfig = {
|
|
131
|
+
withStackTrace: false
|
|
242
132
|
};
|
|
243
|
-
var
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
133
|
+
var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
|
|
134
|
+
const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
|
|
135
|
+
const maybeStack = config.withStackTrace ? new Error().stack : void 0;
|
|
136
|
+
return {
|
|
137
|
+
data,
|
|
138
|
+
message,
|
|
139
|
+
stack: maybeStack
|
|
140
|
+
};
|
|
250
141
|
};
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
parseResponseAsJson: true
|
|
142
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
143
|
+
function adopt(value) {
|
|
144
|
+
return value instanceof P ? value : new P(function(resolve) {
|
|
145
|
+
resolve(value);
|
|
256
146
|
});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (index === -1) {
|
|
265
|
-
return { steps: [], workflowRunEnded: false };
|
|
147
|
+
}
|
|
148
|
+
return new (P || (P = Promise))(function(resolve, reject) {
|
|
149
|
+
function fulfilled(value) {
|
|
150
|
+
try {
|
|
151
|
+
step(generator.next(value));
|
|
152
|
+
} catch (e) {
|
|
153
|
+
reject(e);
|
|
266
154
|
}
|
|
267
|
-
const filteredSteps = steps.slice(0, index + 1);
|
|
268
|
-
await debug?.log("INFO", "ENDPOINT_START", {
|
|
269
|
-
message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
|
|
270
|
-
});
|
|
271
|
-
return { steps: filteredSteps, workflowRunEnded: false };
|
|
272
155
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
return { steps: void 0, workflowRunEnded: true };
|
|
280
|
-
} else {
|
|
281
|
-
throw error;
|
|
156
|
+
function rejected(value) {
|
|
157
|
+
try {
|
|
158
|
+
step(generator["throw"](value));
|
|
159
|
+
} catch (e) {
|
|
160
|
+
reject(e);
|
|
161
|
+
}
|
|
282
162
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// src/context/steps.ts
|
|
287
|
-
var BaseLazyStep = class {
|
|
288
|
-
stepName;
|
|
289
|
-
// will be set in the subclasses
|
|
290
|
-
constructor(stepName) {
|
|
291
|
-
if (!stepName) {
|
|
292
|
-
throw new WorkflowError(
|
|
293
|
-
"A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
this.stepName = stepName;
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
var LazyFunctionStep = class extends BaseLazyStep {
|
|
300
|
-
stepFunction;
|
|
301
|
-
stepType = "Run";
|
|
302
|
-
constructor(stepName, stepFunction) {
|
|
303
|
-
super(stepName);
|
|
304
|
-
this.stepFunction = stepFunction;
|
|
305
|
-
}
|
|
306
|
-
getPlanStep(concurrent, targetStep) {
|
|
307
|
-
return {
|
|
308
|
-
stepId: 0,
|
|
309
|
-
stepName: this.stepName,
|
|
310
|
-
stepType: this.stepType,
|
|
311
|
-
concurrent,
|
|
312
|
-
targetStep
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
async getResultStep(concurrent, stepId) {
|
|
316
|
-
let result = this.stepFunction();
|
|
317
|
-
if (result instanceof Promise) {
|
|
318
|
-
result = await result;
|
|
319
|
-
}
|
|
320
|
-
return {
|
|
321
|
-
stepId,
|
|
322
|
-
stepName: this.stepName,
|
|
323
|
-
stepType: this.stepType,
|
|
324
|
-
out: result,
|
|
325
|
-
concurrent
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
var LazySleepStep = class extends BaseLazyStep {
|
|
330
|
-
sleep;
|
|
331
|
-
stepType = "SleepFor";
|
|
332
|
-
constructor(stepName, sleep) {
|
|
333
|
-
super(stepName);
|
|
334
|
-
this.sleep = sleep;
|
|
335
|
-
}
|
|
336
|
-
getPlanStep(concurrent, targetStep) {
|
|
337
|
-
return {
|
|
338
|
-
stepId: 0,
|
|
339
|
-
stepName: this.stepName,
|
|
340
|
-
stepType: this.stepType,
|
|
341
|
-
sleepFor: this.sleep,
|
|
342
|
-
concurrent,
|
|
343
|
-
targetStep
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
async getResultStep(concurrent, stepId) {
|
|
347
|
-
return await Promise.resolve({
|
|
348
|
-
stepId,
|
|
349
|
-
stepName: this.stepName,
|
|
350
|
-
stepType: this.stepType,
|
|
351
|
-
sleepFor: this.sleep,
|
|
352
|
-
concurrent
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
var LazySleepUntilStep = class extends BaseLazyStep {
|
|
357
|
-
sleepUntil;
|
|
358
|
-
stepType = "SleepUntil";
|
|
359
|
-
constructor(stepName, sleepUntil) {
|
|
360
|
-
super(stepName);
|
|
361
|
-
this.sleepUntil = sleepUntil;
|
|
362
|
-
}
|
|
363
|
-
getPlanStep(concurrent, targetStep) {
|
|
364
|
-
return {
|
|
365
|
-
stepId: 0,
|
|
366
|
-
stepName: this.stepName,
|
|
367
|
-
stepType: this.stepType,
|
|
368
|
-
sleepUntil: this.sleepUntil,
|
|
369
|
-
concurrent,
|
|
370
|
-
targetStep
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
async getResultStep(concurrent, stepId) {
|
|
374
|
-
return await Promise.resolve({
|
|
375
|
-
stepId,
|
|
376
|
-
stepName: this.stepName,
|
|
377
|
-
stepType: this.stepType,
|
|
378
|
-
sleepUntil: this.sleepUntil,
|
|
379
|
-
concurrent
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
var LazyCallStep = class extends BaseLazyStep {
|
|
384
|
-
url;
|
|
385
|
-
method;
|
|
386
|
-
body;
|
|
387
|
-
headers;
|
|
388
|
-
retries;
|
|
389
|
-
timeout;
|
|
390
|
-
stepType = "Call";
|
|
391
|
-
constructor(stepName, url, method, body, headers, retries, timeout) {
|
|
392
|
-
super(stepName);
|
|
393
|
-
this.url = url;
|
|
394
|
-
this.method = method;
|
|
395
|
-
this.body = body;
|
|
396
|
-
this.headers = headers;
|
|
397
|
-
this.retries = retries;
|
|
398
|
-
this.timeout = timeout;
|
|
399
|
-
}
|
|
400
|
-
getPlanStep(concurrent, targetStep) {
|
|
401
|
-
return {
|
|
402
|
-
stepId: 0,
|
|
403
|
-
stepName: this.stepName,
|
|
404
|
-
stepType: this.stepType,
|
|
405
|
-
concurrent,
|
|
406
|
-
targetStep
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
async getResultStep(concurrent, stepId) {
|
|
410
|
-
return await Promise.resolve({
|
|
411
|
-
stepId,
|
|
412
|
-
stepName: this.stepName,
|
|
413
|
-
stepType: this.stepType,
|
|
414
|
-
concurrent,
|
|
415
|
-
callUrl: this.url,
|
|
416
|
-
callMethod: this.method,
|
|
417
|
-
callBody: this.body,
|
|
418
|
-
callHeaders: this.headers
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
var LazyWaitForEventStep = class extends BaseLazyStep {
|
|
423
|
-
eventId;
|
|
424
|
-
timeout;
|
|
425
|
-
stepType = "Wait";
|
|
426
|
-
constructor(stepName, eventId, timeout) {
|
|
427
|
-
super(stepName);
|
|
428
|
-
this.eventId = eventId;
|
|
429
|
-
this.timeout = timeout;
|
|
430
|
-
}
|
|
431
|
-
getPlanStep(concurrent, targetStep) {
|
|
432
|
-
return {
|
|
433
|
-
stepId: 0,
|
|
434
|
-
stepName: this.stepName,
|
|
435
|
-
stepType: this.stepType,
|
|
436
|
-
waitEventId: this.eventId,
|
|
437
|
-
timeout: this.timeout,
|
|
438
|
-
concurrent,
|
|
439
|
-
targetStep
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
async getResultStep(concurrent, stepId) {
|
|
443
|
-
return await Promise.resolve({
|
|
444
|
-
stepId,
|
|
445
|
-
stepName: this.stepName,
|
|
446
|
-
stepType: this.stepType,
|
|
447
|
-
waitEventId: this.eventId,
|
|
448
|
-
timeout: this.timeout,
|
|
449
|
-
concurrent
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
};
|
|
453
|
-
var LazyNotifyStep = class extends LazyFunctionStep {
|
|
454
|
-
stepType = "Notify";
|
|
455
|
-
constructor(stepName, eventId, eventData, requester) {
|
|
456
|
-
super(stepName, async () => {
|
|
457
|
-
const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
|
|
458
|
-
return {
|
|
459
|
-
eventId,
|
|
460
|
-
eventData,
|
|
461
|
-
notifyResponse
|
|
462
|
-
};
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
// node_modules/neverthrow/dist/index.es.js
|
|
468
|
-
var defaultErrorConfig = {
|
|
469
|
-
withStackTrace: false
|
|
470
|
-
};
|
|
471
|
-
var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
|
|
472
|
-
const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
|
|
473
|
-
const maybeStack = config.withStackTrace ? new Error().stack : void 0;
|
|
474
|
-
return {
|
|
475
|
-
data,
|
|
476
|
-
message,
|
|
477
|
-
stack: maybeStack
|
|
478
|
-
};
|
|
479
|
-
};
|
|
480
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
481
|
-
function adopt(value) {
|
|
482
|
-
return value instanceof P ? value : new P(function(resolve) {
|
|
483
|
-
resolve(value);
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
return new (P || (P = Promise))(function(resolve, reject) {
|
|
487
|
-
function fulfilled(value) {
|
|
488
|
-
try {
|
|
489
|
-
step(generator.next(value));
|
|
490
|
-
} catch (e) {
|
|
491
|
-
reject(e);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
function rejected(value) {
|
|
495
|
-
try {
|
|
496
|
-
step(generator["throw"](value));
|
|
497
|
-
} catch (e) {
|
|
498
|
-
reject(e);
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
function step(result) {
|
|
502
|
-
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
163
|
+
function step(result) {
|
|
164
|
+
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
503
165
|
}
|
|
504
166
|
step((generator = generator.apply(thisArg, [])).next());
|
|
505
167
|
});
|
|
@@ -702,556 +364,1154 @@ var combineResultList = (resultList) => {
|
|
|
702
364
|
acc = err(result.error);
|
|
703
365
|
break;
|
|
704
366
|
} else {
|
|
705
|
-
acc.map((list) => list.push(result.value));
|
|
367
|
+
acc.map((list) => list.push(result.value));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return acc;
|
|
371
|
+
};
|
|
372
|
+
var combineResultAsyncList = (asyncResultList) => ResultAsync.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultList);
|
|
373
|
+
var combineResultListWithAllErrors = (resultList) => {
|
|
374
|
+
let acc = ok([]);
|
|
375
|
+
for (const result of resultList) {
|
|
376
|
+
if (result.isErr() && acc.isErr()) {
|
|
377
|
+
acc.error.push(result.error);
|
|
378
|
+
} else if (result.isErr() && acc.isOk()) {
|
|
379
|
+
acc = err([result.error]);
|
|
380
|
+
} else if (result.isOk() && acc.isOk()) {
|
|
381
|
+
acc.value.push(result.value);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return acc;
|
|
385
|
+
};
|
|
386
|
+
var combineResultAsyncListWithAllErrors = (asyncResultList) => ResultAsync.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultListWithAllErrors);
|
|
387
|
+
var Result;
|
|
388
|
+
(function(Result2) {
|
|
389
|
+
function fromThrowable2(fn, errorFn) {
|
|
390
|
+
return (...args) => {
|
|
391
|
+
try {
|
|
392
|
+
const result = fn(...args);
|
|
393
|
+
return ok(result);
|
|
394
|
+
} catch (e) {
|
|
395
|
+
return err(errorFn ? errorFn(e) : e);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
Result2.fromThrowable = fromThrowable2;
|
|
400
|
+
function combine(resultList) {
|
|
401
|
+
return combineResultList(resultList);
|
|
402
|
+
}
|
|
403
|
+
Result2.combine = combine;
|
|
404
|
+
function combineWithAllErrors(resultList) {
|
|
405
|
+
return combineResultListWithAllErrors(resultList);
|
|
406
|
+
}
|
|
407
|
+
Result2.combineWithAllErrors = combineWithAllErrors;
|
|
408
|
+
})(Result || (Result = {}));
|
|
409
|
+
var ok = (value) => new Ok(value);
|
|
410
|
+
function err(err2) {
|
|
411
|
+
return new Err(err2);
|
|
412
|
+
}
|
|
413
|
+
var Ok = class {
|
|
414
|
+
constructor(value) {
|
|
415
|
+
this.value = value;
|
|
416
|
+
}
|
|
417
|
+
isOk() {
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
isErr() {
|
|
421
|
+
return !this.isOk();
|
|
422
|
+
}
|
|
423
|
+
map(f) {
|
|
424
|
+
return ok(f(this.value));
|
|
425
|
+
}
|
|
426
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
427
|
+
mapErr(_f) {
|
|
428
|
+
return ok(this.value);
|
|
429
|
+
}
|
|
430
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
431
|
+
andThen(f) {
|
|
432
|
+
return f(this.value);
|
|
433
|
+
}
|
|
434
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
435
|
+
andThrough(f) {
|
|
436
|
+
return f(this.value).map((_value) => this.value);
|
|
437
|
+
}
|
|
438
|
+
andTee(f) {
|
|
439
|
+
try {
|
|
440
|
+
f(this.value);
|
|
441
|
+
} catch (e) {
|
|
442
|
+
}
|
|
443
|
+
return ok(this.value);
|
|
444
|
+
}
|
|
445
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
446
|
+
orElse(_f) {
|
|
447
|
+
return ok(this.value);
|
|
448
|
+
}
|
|
449
|
+
asyncAndThen(f) {
|
|
450
|
+
return f(this.value);
|
|
451
|
+
}
|
|
452
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
453
|
+
asyncAndThrough(f) {
|
|
454
|
+
return f(this.value).map(() => this.value);
|
|
455
|
+
}
|
|
456
|
+
asyncMap(f) {
|
|
457
|
+
return ResultAsync.fromSafePromise(f(this.value));
|
|
458
|
+
}
|
|
459
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
460
|
+
unwrapOr(_v) {
|
|
461
|
+
return this.value;
|
|
462
|
+
}
|
|
463
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
464
|
+
match(ok2, _err) {
|
|
465
|
+
return ok2(this.value);
|
|
466
|
+
}
|
|
467
|
+
safeUnwrap() {
|
|
468
|
+
const value = this.value;
|
|
469
|
+
return function* () {
|
|
470
|
+
return value;
|
|
471
|
+
}();
|
|
472
|
+
}
|
|
473
|
+
_unsafeUnwrap(_) {
|
|
474
|
+
return this.value;
|
|
475
|
+
}
|
|
476
|
+
_unsafeUnwrapErr(config) {
|
|
477
|
+
throw createNeverThrowError("Called `_unsafeUnwrapErr` on an Ok", this, config);
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
var Err = class {
|
|
481
|
+
constructor(error) {
|
|
482
|
+
this.error = error;
|
|
483
|
+
}
|
|
484
|
+
isOk() {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
isErr() {
|
|
488
|
+
return !this.isOk();
|
|
489
|
+
}
|
|
490
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
491
|
+
map(_f) {
|
|
492
|
+
return err(this.error);
|
|
493
|
+
}
|
|
494
|
+
mapErr(f) {
|
|
495
|
+
return err(f(this.error));
|
|
496
|
+
}
|
|
497
|
+
andThrough(_f) {
|
|
498
|
+
return err(this.error);
|
|
499
|
+
}
|
|
500
|
+
andTee(_f) {
|
|
501
|
+
return err(this.error);
|
|
502
|
+
}
|
|
503
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
504
|
+
andThen(_f) {
|
|
505
|
+
return err(this.error);
|
|
506
|
+
}
|
|
507
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
508
|
+
orElse(f) {
|
|
509
|
+
return f(this.error);
|
|
510
|
+
}
|
|
511
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
512
|
+
asyncAndThen(_f) {
|
|
513
|
+
return errAsync(this.error);
|
|
514
|
+
}
|
|
515
|
+
asyncAndThrough(_f) {
|
|
516
|
+
return errAsync(this.error);
|
|
517
|
+
}
|
|
518
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
519
|
+
asyncMap(_f) {
|
|
520
|
+
return errAsync(this.error);
|
|
521
|
+
}
|
|
522
|
+
unwrapOr(v) {
|
|
523
|
+
return v;
|
|
524
|
+
}
|
|
525
|
+
match(_ok, err2) {
|
|
526
|
+
return err2(this.error);
|
|
527
|
+
}
|
|
528
|
+
safeUnwrap() {
|
|
529
|
+
const error = this.error;
|
|
530
|
+
return function* () {
|
|
531
|
+
yield err(error);
|
|
532
|
+
throw new Error("Do not use this generator out of `safeTry`");
|
|
533
|
+
}();
|
|
534
|
+
}
|
|
535
|
+
_unsafeUnwrap(config) {
|
|
536
|
+
throw createNeverThrowError("Called `_unsafeUnwrap` on an Err", this, config);
|
|
537
|
+
}
|
|
538
|
+
_unsafeUnwrapErr(_) {
|
|
539
|
+
return this.error;
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
var fromThrowable = Result.fromThrowable;
|
|
543
|
+
|
|
544
|
+
// src/workflow-requests.ts
|
|
545
|
+
import { QstashError as QstashError3 } from "@upstash/qstash";
|
|
546
|
+
|
|
547
|
+
// src/client/utils.ts
|
|
548
|
+
import { QstashError as QstashError2 } from "@upstash/qstash";
|
|
549
|
+
var makeNotifyRequest = async (requester, eventId, eventData) => {
|
|
550
|
+
const result = await requester.request({
|
|
551
|
+
path: ["v2", "notify", eventId],
|
|
552
|
+
method: "POST",
|
|
553
|
+
body: typeof eventData === "string" ? eventData : JSON.stringify(eventData)
|
|
554
|
+
});
|
|
555
|
+
return result;
|
|
556
|
+
};
|
|
557
|
+
var makeGetWaitersRequest = async (requester, eventId) => {
|
|
558
|
+
const result = await requester.request({
|
|
559
|
+
path: ["v2", "waiters", eventId],
|
|
560
|
+
method: "GET"
|
|
561
|
+
});
|
|
562
|
+
return result;
|
|
563
|
+
};
|
|
564
|
+
var makeCancelRequest = async (requester, workflowRunId) => {
|
|
565
|
+
await requester.request({
|
|
566
|
+
path: ["v2", "workflows", "runs", `${workflowRunId}?cancel=true`],
|
|
567
|
+
method: "DELETE",
|
|
568
|
+
parseResponseAsJson: false
|
|
569
|
+
});
|
|
570
|
+
return true;
|
|
571
|
+
};
|
|
572
|
+
var getSteps = async (requester, workflowRunId, messageId, debug) => {
|
|
573
|
+
try {
|
|
574
|
+
const steps = await requester.request({
|
|
575
|
+
path: ["v2", "workflows", "runs", workflowRunId],
|
|
576
|
+
parseResponseAsJson: true
|
|
577
|
+
});
|
|
578
|
+
if (!messageId) {
|
|
579
|
+
await debug?.log("INFO", "ENDPOINT_START", {
|
|
580
|
+
message: `Pulled ${steps.length} steps from QStashand returned them without filtering with messageId.`
|
|
581
|
+
});
|
|
582
|
+
return { steps, workflowRunEnded: false };
|
|
583
|
+
} else {
|
|
584
|
+
const index = steps.findIndex((item) => item.messageId === messageId);
|
|
585
|
+
if (index === -1) {
|
|
586
|
+
return { steps: [], workflowRunEnded: false };
|
|
587
|
+
}
|
|
588
|
+
const filteredSteps = steps.slice(0, index + 1);
|
|
589
|
+
await debug?.log("INFO", "ENDPOINT_START", {
|
|
590
|
+
message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
|
|
591
|
+
});
|
|
592
|
+
return { steps: filteredSteps, workflowRunEnded: false };
|
|
593
|
+
}
|
|
594
|
+
} catch (error) {
|
|
595
|
+
if (error instanceof QstashError2 && error.status === 404) {
|
|
596
|
+
await debug?.log("WARN", "ENDPOINT_START", {
|
|
597
|
+
message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
|
|
598
|
+
error
|
|
599
|
+
});
|
|
600
|
+
return { steps: void 0, workflowRunEnded: true };
|
|
601
|
+
} else {
|
|
602
|
+
throw error;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
// src/workflow-requests.ts
|
|
608
|
+
var triggerFirstInvocation = async ({
|
|
609
|
+
workflowContext,
|
|
610
|
+
useJSONContent,
|
|
611
|
+
telemetry,
|
|
612
|
+
debug,
|
|
613
|
+
invokeCount
|
|
614
|
+
}) => {
|
|
615
|
+
const { headers } = getHeaders({
|
|
616
|
+
initHeaderValue: "true",
|
|
617
|
+
workflowRunId: workflowContext.workflowRunId,
|
|
618
|
+
workflowUrl: workflowContext.url,
|
|
619
|
+
userHeaders: workflowContext.headers,
|
|
620
|
+
failureUrl: workflowContext.failureUrl,
|
|
621
|
+
retries: workflowContext.retries,
|
|
622
|
+
telemetry,
|
|
623
|
+
invokeCount,
|
|
624
|
+
flowControl: workflowContext.flowControl
|
|
625
|
+
});
|
|
626
|
+
if (workflowContext.headers.get("content-type")) {
|
|
627
|
+
headers["content-type"] = workflowContext.headers.get("content-type");
|
|
628
|
+
}
|
|
629
|
+
if (useJSONContent) {
|
|
630
|
+
headers["content-type"] = "application/json";
|
|
631
|
+
}
|
|
632
|
+
try {
|
|
633
|
+
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
634
|
+
const result = await workflowContext.qstashClient.publish({
|
|
635
|
+
headers,
|
|
636
|
+
method: "POST",
|
|
637
|
+
body,
|
|
638
|
+
url: workflowContext.url
|
|
639
|
+
});
|
|
640
|
+
if (result.deduplicated) {
|
|
641
|
+
await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
|
|
642
|
+
message: `Workflow run ${workflowContext.workflowRunId} already exists. A new one isn't created.`,
|
|
643
|
+
headers,
|
|
644
|
+
requestPayload: workflowContext.requestPayload,
|
|
645
|
+
url: workflowContext.url,
|
|
646
|
+
messageId: result.messageId
|
|
647
|
+
});
|
|
648
|
+
return ok("workflow-run-already-exists");
|
|
649
|
+
} else {
|
|
650
|
+
await debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
|
|
651
|
+
headers,
|
|
652
|
+
requestPayload: workflowContext.requestPayload,
|
|
653
|
+
url: workflowContext.url,
|
|
654
|
+
messageId: result.messageId
|
|
655
|
+
});
|
|
656
|
+
return ok("success");
|
|
657
|
+
}
|
|
658
|
+
} catch (error) {
|
|
659
|
+
const error_ = error;
|
|
660
|
+
return err(error_);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
var triggerRouteFunction = async ({
|
|
664
|
+
onCleanup,
|
|
665
|
+
onStep,
|
|
666
|
+
onCancel,
|
|
667
|
+
debug
|
|
668
|
+
}) => {
|
|
669
|
+
try {
|
|
670
|
+
const result = await onStep();
|
|
671
|
+
await onCleanup(result);
|
|
672
|
+
return ok("workflow-finished");
|
|
673
|
+
} catch (error) {
|
|
674
|
+
const error_ = error;
|
|
675
|
+
if (error instanceof QstashError3 && error.status === 400) {
|
|
676
|
+
await debug?.log("WARN", "RESPONSE_WORKFLOW", {
|
|
677
|
+
message: `tried to append to a cancelled workflow. exiting without publishing.`,
|
|
678
|
+
name: error.name,
|
|
679
|
+
errorMessage: error.message
|
|
680
|
+
});
|
|
681
|
+
return ok("workflow-was-finished");
|
|
682
|
+
} else if (!(error_ instanceof WorkflowAbort)) {
|
|
683
|
+
return err(error_);
|
|
684
|
+
} else if (error_.cancelWorkflow) {
|
|
685
|
+
await onCancel();
|
|
686
|
+
return ok("workflow-finished");
|
|
687
|
+
} else {
|
|
688
|
+
return ok("step-finished");
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
var triggerWorkflowDelete = async (workflowContext, result, debug, cancel = false) => {
|
|
693
|
+
await debug?.log("SUBMIT", "SUBMIT_CLEANUP", {
|
|
694
|
+
deletedWorkflowRunId: workflowContext.workflowRunId
|
|
695
|
+
});
|
|
696
|
+
await workflowContext.qstashClient.http.request({
|
|
697
|
+
path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
|
|
698
|
+
method: "DELETE",
|
|
699
|
+
parseResponseAsJson: false,
|
|
700
|
+
body: JSON.stringify(result)
|
|
701
|
+
});
|
|
702
|
+
await debug?.log(
|
|
703
|
+
"SUBMIT",
|
|
704
|
+
"SUBMIT_CLEANUP",
|
|
705
|
+
`workflow run ${workflowContext.workflowRunId} deleted.`
|
|
706
|
+
);
|
|
707
|
+
};
|
|
708
|
+
var recreateUserHeaders = (headers) => {
|
|
709
|
+
const filteredHeaders = new Headers();
|
|
710
|
+
const pairs = headers.entries();
|
|
711
|
+
for (const [header, value] of pairs) {
|
|
712
|
+
const headerLowerCase = header.toLowerCase();
|
|
713
|
+
if (!headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
714
|
+
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
715
|
+
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
716
|
+
headerLowerCase !== "render-proxy-ttl") {
|
|
717
|
+
filteredHeaders.append(header, value);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return filteredHeaders;
|
|
721
|
+
};
|
|
722
|
+
var handleThirdPartyCallResult = async ({
|
|
723
|
+
request,
|
|
724
|
+
requestPayload,
|
|
725
|
+
client,
|
|
726
|
+
workflowUrl,
|
|
727
|
+
failureUrl,
|
|
728
|
+
retries,
|
|
729
|
+
telemetry,
|
|
730
|
+
flowControl,
|
|
731
|
+
debug
|
|
732
|
+
}) => {
|
|
733
|
+
try {
|
|
734
|
+
if (request.headers.get("Upstash-Workflow-Callback")) {
|
|
735
|
+
let callbackPayload;
|
|
736
|
+
if (requestPayload) {
|
|
737
|
+
callbackPayload = requestPayload;
|
|
738
|
+
} else {
|
|
739
|
+
const workflowRunId2 = request.headers.get("upstash-workflow-runid");
|
|
740
|
+
const messageId = request.headers.get("upstash-message-id");
|
|
741
|
+
if (!workflowRunId2)
|
|
742
|
+
throw new WorkflowError("workflow run id missing in context.call lazy fetch.");
|
|
743
|
+
if (!messageId) throw new WorkflowError("message id missing in context.call lazy fetch.");
|
|
744
|
+
const { steps, workflowRunEnded } = await getSteps(
|
|
745
|
+
client.http,
|
|
746
|
+
workflowRunId2,
|
|
747
|
+
messageId,
|
|
748
|
+
debug
|
|
749
|
+
);
|
|
750
|
+
if (workflowRunEnded) {
|
|
751
|
+
return ok("workflow-ended");
|
|
752
|
+
}
|
|
753
|
+
const failingStep = steps.find((step) => step.messageId === messageId);
|
|
754
|
+
if (!failingStep)
|
|
755
|
+
throw new WorkflowError(
|
|
756
|
+
"Failed to submit the context.call. " + (steps.length === 0 ? "No steps found." : `No step was found with matching messageId ${messageId} out of ${steps.length} steps.`)
|
|
757
|
+
);
|
|
758
|
+
callbackPayload = atob(failingStep.body);
|
|
759
|
+
}
|
|
760
|
+
const callbackMessage = JSON.parse(callbackPayload);
|
|
761
|
+
if (!(callbackMessage.status >= 200 && callbackMessage.status < 300) && callbackMessage.maxRetries && callbackMessage.retried !== callbackMessage.maxRetries) {
|
|
762
|
+
await debug?.log("WARN", "SUBMIT_THIRD_PARTY_RESULT", {
|
|
763
|
+
status: callbackMessage.status,
|
|
764
|
+
body: atob(callbackMessage.body ?? "")
|
|
765
|
+
});
|
|
766
|
+
console.warn(
|
|
767
|
+
`Workflow Warning: "context.call" failed with status ${callbackMessage.status} and will retry (retried ${callbackMessage.retried ?? 0} out of ${callbackMessage.maxRetries} times). Error Message:
|
|
768
|
+
${atob(callbackMessage.body ?? "")}`
|
|
769
|
+
);
|
|
770
|
+
return ok("call-will-retry");
|
|
771
|
+
}
|
|
772
|
+
const workflowRunId = request.headers.get(WORKFLOW_ID_HEADER);
|
|
773
|
+
const stepIdString = request.headers.get("Upstash-Workflow-StepId");
|
|
774
|
+
const stepName = request.headers.get("Upstash-Workflow-StepName");
|
|
775
|
+
const stepType = request.headers.get("Upstash-Workflow-StepType");
|
|
776
|
+
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
777
|
+
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
778
|
+
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
779
|
+
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
780
|
+
throw new Error(
|
|
781
|
+
`Missing info in callback message source header: ${JSON.stringify({
|
|
782
|
+
workflowRunId,
|
|
783
|
+
stepIdString,
|
|
784
|
+
stepName,
|
|
785
|
+
stepType,
|
|
786
|
+
concurrentString,
|
|
787
|
+
contentType
|
|
788
|
+
})}`
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
const userHeaders = recreateUserHeaders(request.headers);
|
|
792
|
+
const { headers: requestHeaders } = getHeaders({
|
|
793
|
+
initHeaderValue: "false",
|
|
794
|
+
workflowRunId,
|
|
795
|
+
workflowUrl,
|
|
796
|
+
userHeaders,
|
|
797
|
+
failureUrl,
|
|
798
|
+
retries,
|
|
799
|
+
telemetry,
|
|
800
|
+
invokeCount: Number(invokeCount),
|
|
801
|
+
flowControl
|
|
802
|
+
});
|
|
803
|
+
const callResponse = {
|
|
804
|
+
status: callbackMessage.status,
|
|
805
|
+
body: atob(callbackMessage.body ?? ""),
|
|
806
|
+
header: callbackMessage.header
|
|
807
|
+
};
|
|
808
|
+
const callResultStep = {
|
|
809
|
+
stepId: Number(stepIdString),
|
|
810
|
+
stepName,
|
|
811
|
+
stepType,
|
|
812
|
+
out: JSON.stringify(callResponse),
|
|
813
|
+
concurrent: Number(concurrentString)
|
|
814
|
+
};
|
|
815
|
+
await debug?.log("SUBMIT", "SUBMIT_THIRD_PARTY_RESULT", {
|
|
816
|
+
step: callResultStep,
|
|
817
|
+
headers: requestHeaders,
|
|
818
|
+
url: workflowUrl
|
|
819
|
+
});
|
|
820
|
+
const result = await client.publishJSON({
|
|
821
|
+
headers: requestHeaders,
|
|
822
|
+
method: "POST",
|
|
823
|
+
body: callResultStep,
|
|
824
|
+
url: workflowUrl
|
|
825
|
+
});
|
|
826
|
+
await debug?.log("SUBMIT", "SUBMIT_THIRD_PARTY_RESULT", {
|
|
827
|
+
messageId: result.messageId
|
|
828
|
+
});
|
|
829
|
+
return ok("is-call-return");
|
|
830
|
+
} else {
|
|
831
|
+
return ok("continue-workflow");
|
|
706
832
|
}
|
|
833
|
+
} catch (error) {
|
|
834
|
+
const isCallReturn = request.headers.get("Upstash-Workflow-Callback");
|
|
835
|
+
return err(
|
|
836
|
+
new WorkflowError(`Error when handling call return (isCallReturn=${isCallReturn}): ${error}`)
|
|
837
|
+
);
|
|
707
838
|
}
|
|
708
|
-
return acc;
|
|
709
839
|
};
|
|
710
|
-
var
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
} else if (result.isErr() && acc.isOk()) {
|
|
717
|
-
acc = err([result.error]);
|
|
718
|
-
} else if (result.isOk() && acc.isOk()) {
|
|
719
|
-
acc.value.push(result.value);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
return acc;
|
|
840
|
+
var getTelemetryHeaders = (telemetry) => {
|
|
841
|
+
return {
|
|
842
|
+
[TELEMETRY_HEADER_SDK]: telemetry.sdk,
|
|
843
|
+
[TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
|
|
844
|
+
[TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
|
|
845
|
+
};
|
|
723
846
|
};
|
|
724
|
-
var
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
var Ok = class {
|
|
752
|
-
constructor(value) {
|
|
753
|
-
this.value = value;
|
|
754
|
-
}
|
|
755
|
-
isOk() {
|
|
756
|
-
return true;
|
|
757
|
-
}
|
|
758
|
-
isErr() {
|
|
759
|
-
return !this.isOk();
|
|
760
|
-
}
|
|
761
|
-
map(f) {
|
|
762
|
-
return ok(f(this.value));
|
|
763
|
-
}
|
|
764
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
765
|
-
mapErr(_f) {
|
|
766
|
-
return ok(this.value);
|
|
847
|
+
var getHeaders = ({
|
|
848
|
+
initHeaderValue,
|
|
849
|
+
workflowRunId,
|
|
850
|
+
workflowUrl,
|
|
851
|
+
userHeaders,
|
|
852
|
+
failureUrl,
|
|
853
|
+
retries,
|
|
854
|
+
step,
|
|
855
|
+
callRetries,
|
|
856
|
+
callTimeout,
|
|
857
|
+
telemetry,
|
|
858
|
+
invokeCount,
|
|
859
|
+
flowControl,
|
|
860
|
+
callFlowControl
|
|
861
|
+
}) => {
|
|
862
|
+
const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
863
|
+
const baseHeaders = {
|
|
864
|
+
[WORKFLOW_INIT_HEADER]: initHeaderValue,
|
|
865
|
+
[WORKFLOW_ID_HEADER]: workflowRunId,
|
|
866
|
+
[WORKFLOW_URL_HEADER]: workflowUrl,
|
|
867
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
868
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
869
|
+
"content-type": contentType,
|
|
870
|
+
...telemetry ? getTelemetryHeaders(telemetry) : {}
|
|
871
|
+
};
|
|
872
|
+
if (invokeCount !== void 0 && !step?.callUrl) {
|
|
873
|
+
baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
|
|
767
874
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
return f(this.value);
|
|
875
|
+
if (!step?.callUrl) {
|
|
876
|
+
baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
771
877
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
return f(this.value).map((_value) => this.value);
|
|
878
|
+
if (callTimeout) {
|
|
879
|
+
baseHeaders[`Upstash-Timeout`] = callTimeout.toString();
|
|
775
880
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
881
|
+
if (failureUrl) {
|
|
882
|
+
baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
|
|
883
|
+
baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
|
|
884
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
|
|
885
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
|
|
886
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
|
|
887
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
|
|
888
|
+
if (retries !== void 0) {
|
|
889
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
890
|
+
}
|
|
891
|
+
if (flowControl) {
|
|
892
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
893
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
|
|
894
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
|
|
895
|
+
}
|
|
896
|
+
if (!step?.callUrl) {
|
|
897
|
+
baseHeaders["Upstash-Failure-Callback"] = failureUrl;
|
|
780
898
|
}
|
|
781
|
-
return ok(this.value);
|
|
782
|
-
}
|
|
783
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
784
|
-
orElse(_f) {
|
|
785
|
-
return ok(this.value);
|
|
786
|
-
}
|
|
787
|
-
asyncAndThen(f) {
|
|
788
|
-
return f(this.value);
|
|
789
|
-
}
|
|
790
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
791
|
-
asyncAndThrough(f) {
|
|
792
|
-
return f(this.value).map(() => this.value);
|
|
793
|
-
}
|
|
794
|
-
asyncMap(f) {
|
|
795
|
-
return ResultAsync.fromSafePromise(f(this.value));
|
|
796
|
-
}
|
|
797
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
798
|
-
unwrapOr(_v) {
|
|
799
|
-
return this.value;
|
|
800
|
-
}
|
|
801
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
802
|
-
match(ok2, _err) {
|
|
803
|
-
return ok2(this.value);
|
|
804
|
-
}
|
|
805
|
-
safeUnwrap() {
|
|
806
|
-
const value = this.value;
|
|
807
|
-
return function* () {
|
|
808
|
-
return value;
|
|
809
|
-
}();
|
|
810
|
-
}
|
|
811
|
-
_unsafeUnwrap(_) {
|
|
812
|
-
return this.value;
|
|
813
|
-
}
|
|
814
|
-
_unsafeUnwrapErr(config) {
|
|
815
|
-
throw createNeverThrowError("Called `_unsafeUnwrapErr` on an Ok", this, config);
|
|
816
|
-
}
|
|
817
|
-
};
|
|
818
|
-
var Err = class {
|
|
819
|
-
constructor(error) {
|
|
820
|
-
this.error = error;
|
|
821
|
-
}
|
|
822
|
-
isOk() {
|
|
823
|
-
return false;
|
|
824
|
-
}
|
|
825
|
-
isErr() {
|
|
826
|
-
return !this.isOk();
|
|
827
|
-
}
|
|
828
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
829
|
-
map(_f) {
|
|
830
|
-
return err(this.error);
|
|
831
|
-
}
|
|
832
|
-
mapErr(f) {
|
|
833
|
-
return err(f(this.error));
|
|
834
|
-
}
|
|
835
|
-
andThrough(_f) {
|
|
836
|
-
return err(this.error);
|
|
837
|
-
}
|
|
838
|
-
andTee(_f) {
|
|
839
|
-
return err(this.error);
|
|
840
|
-
}
|
|
841
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
842
|
-
andThen(_f) {
|
|
843
|
-
return err(this.error);
|
|
844
|
-
}
|
|
845
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
846
|
-
orElse(f) {
|
|
847
|
-
return f(this.error);
|
|
848
|
-
}
|
|
849
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
850
|
-
asyncAndThen(_f) {
|
|
851
|
-
return errAsync(this.error);
|
|
852
899
|
}
|
|
853
|
-
|
|
854
|
-
|
|
900
|
+
if (step?.callUrl) {
|
|
901
|
+
baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
|
|
902
|
+
baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
903
|
+
if (retries !== void 0) {
|
|
904
|
+
baseHeaders["Upstash-Callback-Retries"] = retries.toString();
|
|
905
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
906
|
+
}
|
|
907
|
+
if (callFlowControl) {
|
|
908
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
|
|
909
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
910
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
911
|
+
}
|
|
912
|
+
if (flowControl) {
|
|
913
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
914
|
+
baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
|
|
915
|
+
baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
|
|
916
|
+
}
|
|
917
|
+
} else {
|
|
918
|
+
if (flowControl) {
|
|
919
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
920
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
921
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
922
|
+
}
|
|
923
|
+
if (retries !== void 0) {
|
|
924
|
+
baseHeaders["Upstash-Retries"] = retries.toString();
|
|
925
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
926
|
+
}
|
|
855
927
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
928
|
+
if (userHeaders) {
|
|
929
|
+
for (const header of userHeaders.keys()) {
|
|
930
|
+
if (step?.callHeaders) {
|
|
931
|
+
baseHeaders[`Upstash-Callback-Forward-${header}`] = userHeaders.get(header);
|
|
932
|
+
} else {
|
|
933
|
+
baseHeaders[`Upstash-Forward-${header}`] = userHeaders.get(header);
|
|
934
|
+
}
|
|
935
|
+
baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
|
|
936
|
+
}
|
|
859
937
|
}
|
|
860
|
-
|
|
861
|
-
|
|
938
|
+
if (step?.callHeaders) {
|
|
939
|
+
const forwardedHeaders = Object.fromEntries(
|
|
940
|
+
Object.entries(step.callHeaders).map(([header, value]) => [
|
|
941
|
+
`Upstash-Forward-${header}`,
|
|
942
|
+
value
|
|
943
|
+
])
|
|
944
|
+
);
|
|
945
|
+
return {
|
|
946
|
+
headers: {
|
|
947
|
+
...baseHeaders,
|
|
948
|
+
...forwardedHeaders,
|
|
949
|
+
"Upstash-Callback": workflowUrl,
|
|
950
|
+
"Upstash-Callback-Workflow-RunId": workflowRunId,
|
|
951
|
+
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
952
|
+
"Upstash-Callback-Workflow-Init": "false",
|
|
953
|
+
"Upstash-Callback-Workflow-Url": workflowUrl,
|
|
954
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
955
|
+
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
956
|
+
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
957
|
+
"Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
|
|
958
|
+
"Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
|
|
959
|
+
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
960
|
+
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
961
|
+
[`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
|
|
962
|
+
"Upstash-Workflow-CallType": "toCallback"
|
|
963
|
+
}
|
|
964
|
+
};
|
|
862
965
|
}
|
|
863
|
-
|
|
864
|
-
return
|
|
966
|
+
if (step?.waitEventId) {
|
|
967
|
+
return {
|
|
968
|
+
headers: {
|
|
969
|
+
...baseHeaders,
|
|
970
|
+
"Upstash-Workflow-CallType": "step"
|
|
971
|
+
},
|
|
972
|
+
timeoutHeaders: {
|
|
973
|
+
// to include user headers:
|
|
974
|
+
...Object.fromEntries(
|
|
975
|
+
Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
|
|
976
|
+
),
|
|
977
|
+
// to include telemetry headers:
|
|
978
|
+
...telemetry ? Object.fromEntries(
|
|
979
|
+
Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
|
|
980
|
+
header,
|
|
981
|
+
[value]
|
|
982
|
+
])
|
|
983
|
+
) : {},
|
|
984
|
+
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
985
|
+
"Upstash-Workflow-Runid": [workflowRunId],
|
|
986
|
+
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
987
|
+
[WORKFLOW_URL_HEADER]: [workflowUrl],
|
|
988
|
+
"Upstash-Workflow-CallType": ["step"]
|
|
989
|
+
}
|
|
990
|
+
};
|
|
865
991
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
}();
|
|
992
|
+
return { headers: baseHeaders };
|
|
993
|
+
};
|
|
994
|
+
var verifyRequest = async (body, signature, verifier) => {
|
|
995
|
+
if (!verifier) {
|
|
996
|
+
return;
|
|
872
997
|
}
|
|
873
|
-
|
|
874
|
-
|
|
998
|
+
try {
|
|
999
|
+
if (!signature) {
|
|
1000
|
+
throw new Error("`Upstash-Signature` header is not passed.");
|
|
1001
|
+
}
|
|
1002
|
+
const isValid = await verifier.verify({
|
|
1003
|
+
body,
|
|
1004
|
+
signature
|
|
1005
|
+
});
|
|
1006
|
+
if (!isValid) {
|
|
1007
|
+
throw new Error("Signature in `Upstash-Signature` header is not valid");
|
|
1008
|
+
}
|
|
1009
|
+
} catch (error) {
|
|
1010
|
+
throw new WorkflowError(
|
|
1011
|
+
`Failed to verify that the Workflow request comes from QStash: ${error}
|
|
1012
|
+
|
|
1013
|
+
If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
|
|
1014
|
+
|
|
1015
|
+
If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
|
|
1016
|
+
);
|
|
875
1017
|
}
|
|
876
|
-
|
|
877
|
-
|
|
1018
|
+
};
|
|
1019
|
+
var prepareFlowControl = (flowControl) => {
|
|
1020
|
+
const parallelism = flowControl.parallelism?.toString();
|
|
1021
|
+
const rate = flowControl.ratePerSecond?.toString();
|
|
1022
|
+
const controlValue = [
|
|
1023
|
+
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
1024
|
+
rate ? `rate=${rate}` : void 0
|
|
1025
|
+
].filter(Boolean);
|
|
1026
|
+
if (controlValue.length === 0) {
|
|
1027
|
+
throw new QstashError3("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
878
1028
|
}
|
|
1029
|
+
return {
|
|
1030
|
+
flowControlKey: flowControl.key,
|
|
1031
|
+
flowControlValue: controlValue.join(", ")
|
|
1032
|
+
};
|
|
879
1033
|
};
|
|
880
|
-
var fromThrowable = Result.fromThrowable;
|
|
881
1034
|
|
|
882
|
-
// src/
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1035
|
+
// src/serve/serve-many.ts
|
|
1036
|
+
var getWorkflowId = (url) => {
|
|
1037
|
+
const components = url.split("/");
|
|
1038
|
+
const lastComponent = components[components.length - 1];
|
|
1039
|
+
return lastComponent.split("?")[0];
|
|
1040
|
+
};
|
|
1041
|
+
var serveManyBase = ({
|
|
1042
|
+
workflows,
|
|
1043
|
+
getUrl,
|
|
1044
|
+
serveMethod,
|
|
1045
|
+
options
|
|
889
1046
|
}) => {
|
|
890
|
-
const
|
|
1047
|
+
const workflowIds = [];
|
|
1048
|
+
const workflowMap = Object.fromEntries(
|
|
1049
|
+
Object.entries(workflows).map((workflow) => {
|
|
1050
|
+
const workflowId = workflow[0];
|
|
1051
|
+
if (workflowIds.includes(workflowId)) {
|
|
1052
|
+
throw new WorkflowError(
|
|
1053
|
+
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
if (workflowId.includes("/")) {
|
|
1057
|
+
throw new WorkflowError(
|
|
1058
|
+
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
workflowIds.push(workflowId);
|
|
1062
|
+
workflow[1].workflowId = workflowId;
|
|
1063
|
+
workflow[1].options = {
|
|
1064
|
+
...options,
|
|
1065
|
+
...workflow[1].options
|
|
1066
|
+
};
|
|
1067
|
+
const params = [workflow[1].routeFunction, workflow[1].options];
|
|
1068
|
+
const handler = serveMethod(...params);
|
|
1069
|
+
return [workflowId, handler];
|
|
1070
|
+
})
|
|
1071
|
+
);
|
|
1072
|
+
return {
|
|
1073
|
+
handler: async (...params) => {
|
|
1074
|
+
const url = getUrl(...params);
|
|
1075
|
+
const pickedWorkflowId = getWorkflowId(url);
|
|
1076
|
+
if (!pickedWorkflowId) {
|
|
1077
|
+
return new Response(
|
|
1078
|
+
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
1079
|
+
{
|
|
1080
|
+
status: 404
|
|
1081
|
+
}
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
const workflow = workflowMap[pickedWorkflowId];
|
|
1085
|
+
if (!workflow) {
|
|
1086
|
+
return new Response(
|
|
1087
|
+
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
1088
|
+
{
|
|
1089
|
+
status: 404
|
|
1090
|
+
}
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
return await workflow(...params);
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
};
|
|
1097
|
+
var invokeWorkflow = async ({
|
|
1098
|
+
settings,
|
|
1099
|
+
invokeStep,
|
|
1100
|
+
context,
|
|
1101
|
+
invokeCount,
|
|
1102
|
+
telemetry
|
|
1103
|
+
}) => {
|
|
1104
|
+
const {
|
|
1105
|
+
body,
|
|
1106
|
+
workflow,
|
|
1107
|
+
headers = {},
|
|
1108
|
+
workflowRunId = getWorkflowRunId(),
|
|
1109
|
+
retries,
|
|
1110
|
+
flowControl
|
|
1111
|
+
} = settings;
|
|
1112
|
+
const { workflowId } = workflow;
|
|
1113
|
+
const {
|
|
1114
|
+
retries: workflowRetries,
|
|
1115
|
+
failureFunction,
|
|
1116
|
+
failureUrl,
|
|
1117
|
+
useJSONContent,
|
|
1118
|
+
flowControl: workflowFlowControl
|
|
1119
|
+
} = workflow.options;
|
|
1120
|
+
if (!workflowId) {
|
|
1121
|
+
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
1122
|
+
}
|
|
1123
|
+
const { headers: invokerHeaders } = getHeaders({
|
|
1124
|
+
initHeaderValue: "false",
|
|
1125
|
+
workflowRunId: context.workflowRunId,
|
|
1126
|
+
workflowUrl: context.url,
|
|
1127
|
+
userHeaders: context.headers,
|
|
1128
|
+
failureUrl: context.failureUrl,
|
|
1129
|
+
retries: context.retries,
|
|
1130
|
+
telemetry,
|
|
1131
|
+
invokeCount,
|
|
1132
|
+
flowControl: context.flowControl
|
|
1133
|
+
});
|
|
1134
|
+
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1135
|
+
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
1136
|
+
const { headers: triggerHeaders } = getHeaders({
|
|
891
1137
|
initHeaderValue: "true",
|
|
892
|
-
workflowRunId
|
|
893
|
-
workflowUrl:
|
|
894
|
-
userHeaders:
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1138
|
+
workflowRunId,
|
|
1139
|
+
workflowUrl: newUrl,
|
|
1140
|
+
userHeaders: new Headers(headers),
|
|
1141
|
+
retries: retries ?? workflowRetries,
|
|
1142
|
+
telemetry,
|
|
1143
|
+
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1144
|
+
invokeCount: invokeCount + 1,
|
|
1145
|
+
flowControl: flowControl ?? workflowFlowControl
|
|
898
1146
|
});
|
|
899
|
-
|
|
900
|
-
headers["content-type"] = workflowContext.headers.get("content-type");
|
|
901
|
-
}
|
|
1147
|
+
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
902
1148
|
if (useJSONContent) {
|
|
903
|
-
|
|
1149
|
+
triggerHeaders["content-type"] = "application/json";
|
|
904
1150
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1151
|
+
const request = {
|
|
1152
|
+
body: JSON.stringify(body),
|
|
1153
|
+
headers: Object.fromEntries(
|
|
1154
|
+
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1155
|
+
),
|
|
1156
|
+
workflowRunId,
|
|
1157
|
+
workflowUrl: context.url,
|
|
1158
|
+
step: invokeStep
|
|
1159
|
+
};
|
|
1160
|
+
await context.qstashClient.publish({
|
|
1161
|
+
headers: triggerHeaders,
|
|
1162
|
+
method: "POST",
|
|
1163
|
+
body: JSON.stringify(request),
|
|
1164
|
+
url: newUrl
|
|
1165
|
+
});
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
// src/agents/adapters.ts
|
|
1169
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
1170
|
+
import { tool } from "ai";
|
|
1171
|
+
|
|
1172
|
+
// src/agents/constants.ts
|
|
1173
|
+
var AGENT_NAME_HEADER = "upstash-agent-name";
|
|
1174
|
+
var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
|
|
1175
|
+
|
|
1176
|
+
These other agents have tools available to them.
|
|
1177
|
+
|
|
1178
|
+
Given a prompt, utilize these agents to address requests.
|
|
1179
|
+
|
|
1180
|
+
Don't always call all the agents provided to you at the same time. You can call one and use it's response to call another.
|
|
1181
|
+
|
|
1182
|
+
Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
|
|
1183
|
+
you need from that agent.
|
|
1184
|
+
`;
|
|
1185
|
+
|
|
1186
|
+
// src/agents/adapters.ts
|
|
1187
|
+
var createWorkflowOpenAI = (context, config) => {
|
|
1188
|
+
const { baseURL, apiKey } = config ?? {};
|
|
1189
|
+
return createOpenAI({
|
|
1190
|
+
baseURL,
|
|
1191
|
+
apiKey,
|
|
1192
|
+
compatibility: "strict",
|
|
1193
|
+
fetch: async (input, init) => {
|
|
1194
|
+
try {
|
|
1195
|
+
const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
|
|
1196
|
+
const body = init?.body ? JSON.parse(init.body) : void 0;
|
|
1197
|
+
const agentName = headers[AGENT_NAME_HEADER];
|
|
1198
|
+
const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
|
|
1199
|
+
const responseInfo = await context.call(stepName, {
|
|
1200
|
+
url: input.toString(),
|
|
1201
|
+
method: init?.method,
|
|
1202
|
+
headers,
|
|
1203
|
+
body
|
|
1204
|
+
});
|
|
1205
|
+
const responseHeaders = new Headers(
|
|
1206
|
+
Object.entries(responseInfo.header).reduce(
|
|
1207
|
+
(acc, [key, values]) => {
|
|
1208
|
+
acc[key] = values.join(", ");
|
|
1209
|
+
return acc;
|
|
1210
|
+
},
|
|
1211
|
+
{}
|
|
1212
|
+
)
|
|
1213
|
+
);
|
|
1214
|
+
return new Response(JSON.stringify(responseInfo.body), {
|
|
1215
|
+
status: responseInfo.status,
|
|
1216
|
+
headers: responseHeaders
|
|
1217
|
+
});
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
if (error instanceof Error && error.name === "WorkflowAbort") {
|
|
1220
|
+
throw error;
|
|
1221
|
+
} else {
|
|
1222
|
+
console.error("Error in fetch implementation:", error);
|
|
1223
|
+
throw error;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
930
1226
|
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
|
|
1227
|
+
});
|
|
1228
|
+
};
|
|
1229
|
+
var wrapTools = ({
|
|
1230
|
+
context,
|
|
1231
|
+
tools
|
|
1232
|
+
}) => {
|
|
1233
|
+
return Object.fromEntries(
|
|
1234
|
+
Object.entries(tools).map((toolInfo) => {
|
|
1235
|
+
const [toolName, tool3] = toolInfo;
|
|
1236
|
+
const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
|
|
1237
|
+
const aiSDKTool = convertToAISDKTool(tool3);
|
|
1238
|
+
const execute = aiSDKTool.execute;
|
|
1239
|
+
if (execute && executeAsStep) {
|
|
1240
|
+
const wrappedExecute = (...params) => {
|
|
1241
|
+
return context.run(`Run tool ${toolName}`, () => execute(...params));
|
|
1242
|
+
};
|
|
1243
|
+
aiSDKTool.execute = wrappedExecute;
|
|
1244
|
+
}
|
|
1245
|
+
return [toolName, aiSDKTool];
|
|
1246
|
+
})
|
|
1247
|
+
);
|
|
1248
|
+
};
|
|
1249
|
+
var convertToAISDKTool = (tool3) => {
|
|
1250
|
+
const isLangchainTool = "invoke" in tool3;
|
|
1251
|
+
return isLangchainTool ? convertLangchainTool(tool3) : tool3;
|
|
1252
|
+
};
|
|
1253
|
+
var convertLangchainTool = (langchainTool) => {
|
|
1254
|
+
return tool({
|
|
1255
|
+
description: langchainTool.description,
|
|
1256
|
+
parameters: langchainTool.schema,
|
|
1257
|
+
execute: async (...param) => langchainTool.invoke(...param)
|
|
1258
|
+
});
|
|
1259
|
+
};
|
|
1260
|
+
var WorkflowTool = class {
|
|
1261
|
+
/**
|
|
1262
|
+
* description of the tool
|
|
1263
|
+
*/
|
|
1264
|
+
description;
|
|
1265
|
+
/**
|
|
1266
|
+
* schema of the tool
|
|
1267
|
+
*/
|
|
1268
|
+
schema;
|
|
1269
|
+
/**
|
|
1270
|
+
* function to invoke the tool
|
|
1271
|
+
*/
|
|
1272
|
+
invoke;
|
|
1273
|
+
/**
|
|
1274
|
+
* whether the invoke method of the tool is to be wrapped with `context.run`
|
|
1275
|
+
*/
|
|
1276
|
+
executeAsStep;
|
|
1277
|
+
/**
|
|
1278
|
+
*
|
|
1279
|
+
* @param description description of the tool
|
|
1280
|
+
* @param schema schema of the tool
|
|
1281
|
+
* @param invoke function to invoke the tool
|
|
1282
|
+
* @param executeAsStep whether the invoke method of the tool is to be wrapped with `context.run`
|
|
1283
|
+
*/
|
|
1284
|
+
constructor(params) {
|
|
1285
|
+
this.description = params.description;
|
|
1286
|
+
this.schema = params.schema;
|
|
1287
|
+
this.invoke = params.invoke;
|
|
1288
|
+
this.executeAsStep = params.executeAsStep ?? true;
|
|
934
1289
|
}
|
|
935
1290
|
};
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
} catch (error) {
|
|
947
|
-
const error_ = error;
|
|
948
|
-
if (error instanceof QstashError3 && error.status === 400) {
|
|
949
|
-
await debug?.log("WARN", "RESPONSE_WORKFLOW", {
|
|
950
|
-
message: `tried to append to a cancelled workflow. exiting without publishing.`,
|
|
951
|
-
name: error.name,
|
|
952
|
-
errorMessage: error.message
|
|
953
|
-
});
|
|
954
|
-
return ok("workflow-was-finished");
|
|
955
|
-
} else if (!(error_ instanceof WorkflowAbort)) {
|
|
956
|
-
return err(error_);
|
|
957
|
-
} else if (error_.cancelWorkflow) {
|
|
958
|
-
await onCancel();
|
|
959
|
-
return ok("workflow-finished");
|
|
960
|
-
} else {
|
|
961
|
-
return ok("step-finished");
|
|
1291
|
+
|
|
1292
|
+
// src/context/steps.ts
|
|
1293
|
+
var BaseLazyStep = class {
|
|
1294
|
+
stepName;
|
|
1295
|
+
// will be set in the subclasses
|
|
1296
|
+
constructor(stepName) {
|
|
1297
|
+
if (!stepName) {
|
|
1298
|
+
throw new WorkflowError(
|
|
1299
|
+
"A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
|
|
1300
|
+
);
|
|
962
1301
|
}
|
|
1302
|
+
this.stepName = stepName;
|
|
963
1303
|
}
|
|
964
1304
|
};
|
|
965
|
-
var
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
method: "DELETE",
|
|
972
|
-
parseResponseAsJson: false
|
|
973
|
-
});
|
|
974
|
-
await debug?.log(
|
|
975
|
-
"SUBMIT",
|
|
976
|
-
"SUBMIT_CLEANUP",
|
|
977
|
-
`workflow run ${workflowContext.workflowRunId} deleted.`
|
|
978
|
-
);
|
|
979
|
-
};
|
|
980
|
-
var recreateUserHeaders = (headers) => {
|
|
981
|
-
const filteredHeaders = new Headers();
|
|
982
|
-
const pairs = headers.entries();
|
|
983
|
-
for (const [header, value] of pairs) {
|
|
984
|
-
const headerLowerCase = header.toLowerCase();
|
|
985
|
-
if (!headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
986
|
-
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
987
|
-
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
988
|
-
headerLowerCase !== "render-proxy-ttl") {
|
|
989
|
-
filteredHeaders.append(header, value);
|
|
990
|
-
}
|
|
1305
|
+
var LazyFunctionStep = class extends BaseLazyStep {
|
|
1306
|
+
stepFunction;
|
|
1307
|
+
stepType = "Run";
|
|
1308
|
+
constructor(stepName, stepFunction) {
|
|
1309
|
+
super(stepName);
|
|
1310
|
+
this.stepFunction = stepFunction;
|
|
991
1311
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
if (request.headers.get("Upstash-Workflow-Callback")) {
|
|
1006
|
-
let callbackPayload;
|
|
1007
|
-
if (requestPayload) {
|
|
1008
|
-
callbackPayload = requestPayload;
|
|
1009
|
-
} else {
|
|
1010
|
-
const workflowRunId2 = request.headers.get("upstash-workflow-runid");
|
|
1011
|
-
const messageId = request.headers.get("upstash-message-id");
|
|
1012
|
-
if (!workflowRunId2)
|
|
1013
|
-
throw new WorkflowError("workflow run id missing in context.call lazy fetch.");
|
|
1014
|
-
if (!messageId) throw new WorkflowError("message id missing in context.call lazy fetch.");
|
|
1015
|
-
const { steps, workflowRunEnded } = await getSteps(
|
|
1016
|
-
client.http,
|
|
1017
|
-
workflowRunId2,
|
|
1018
|
-
messageId,
|
|
1019
|
-
debug
|
|
1020
|
-
);
|
|
1021
|
-
if (workflowRunEnded) {
|
|
1022
|
-
return ok("workflow-ended");
|
|
1023
|
-
}
|
|
1024
|
-
const failingStep = steps.find((step) => step.messageId === messageId);
|
|
1025
|
-
if (!failingStep)
|
|
1026
|
-
throw new WorkflowError(
|
|
1027
|
-
"Failed to submit the context.call. " + (steps.length === 0 ? "No steps found." : `No step was found with matching messageId ${messageId} out of ${steps.length} steps.`)
|
|
1028
|
-
);
|
|
1029
|
-
callbackPayload = atob(failingStep.body);
|
|
1030
|
-
}
|
|
1031
|
-
const callbackMessage = JSON.parse(callbackPayload);
|
|
1032
|
-
if (!(callbackMessage.status >= 200 && callbackMessage.status < 300) && callbackMessage.maxRetries && callbackMessage.retried !== callbackMessage.maxRetries) {
|
|
1033
|
-
await debug?.log("WARN", "SUBMIT_THIRD_PARTY_RESULT", {
|
|
1034
|
-
status: callbackMessage.status,
|
|
1035
|
-
body: atob(callbackMessage.body ?? "")
|
|
1036
|
-
});
|
|
1037
|
-
console.warn(
|
|
1038
|
-
`Workflow Warning: "context.call" failed with status ${callbackMessage.status} and will retry (retried ${callbackMessage.retried ?? 0} out of ${callbackMessage.maxRetries} times). Error Message:
|
|
1039
|
-
${atob(callbackMessage.body ?? "")}`
|
|
1040
|
-
);
|
|
1041
|
-
return ok("call-will-retry");
|
|
1042
|
-
}
|
|
1043
|
-
const workflowRunId = request.headers.get(WORKFLOW_ID_HEADER);
|
|
1044
|
-
const stepIdString = request.headers.get("Upstash-Workflow-StepId");
|
|
1045
|
-
const stepName = request.headers.get("Upstash-Workflow-StepName");
|
|
1046
|
-
const stepType = request.headers.get("Upstash-Workflow-StepType");
|
|
1047
|
-
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
1048
|
-
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
1049
|
-
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
1050
|
-
throw new Error(
|
|
1051
|
-
`Missing info in callback message source header: ${JSON.stringify({
|
|
1052
|
-
workflowRunId,
|
|
1053
|
-
stepIdString,
|
|
1054
|
-
stepName,
|
|
1055
|
-
stepType,
|
|
1056
|
-
concurrentString,
|
|
1057
|
-
contentType
|
|
1058
|
-
})}`
|
|
1059
|
-
);
|
|
1060
|
-
}
|
|
1061
|
-
const userHeaders = recreateUserHeaders(request.headers);
|
|
1062
|
-
const { headers: requestHeaders } = getHeaders({
|
|
1063
|
-
initHeaderValue: "false",
|
|
1064
|
-
workflowRunId,
|
|
1065
|
-
workflowUrl,
|
|
1066
|
-
userHeaders,
|
|
1067
|
-
failureUrl,
|
|
1068
|
-
retries,
|
|
1069
|
-
telemetry
|
|
1070
|
-
});
|
|
1071
|
-
const callResponse = {
|
|
1072
|
-
status: callbackMessage.status,
|
|
1073
|
-
body: atob(callbackMessage.body ?? ""),
|
|
1074
|
-
header: callbackMessage.header
|
|
1075
|
-
};
|
|
1076
|
-
const callResultStep = {
|
|
1077
|
-
stepId: Number(stepIdString),
|
|
1078
|
-
stepName,
|
|
1079
|
-
stepType,
|
|
1080
|
-
out: JSON.stringify(callResponse),
|
|
1081
|
-
concurrent: Number(concurrentString)
|
|
1082
|
-
};
|
|
1083
|
-
await debug?.log("SUBMIT", "SUBMIT_THIRD_PARTY_RESULT", {
|
|
1084
|
-
step: callResultStep,
|
|
1085
|
-
headers: requestHeaders,
|
|
1086
|
-
url: workflowUrl
|
|
1087
|
-
});
|
|
1088
|
-
const result = await client.publishJSON({
|
|
1089
|
-
headers: requestHeaders,
|
|
1090
|
-
method: "POST",
|
|
1091
|
-
body: callResultStep,
|
|
1092
|
-
url: workflowUrl
|
|
1093
|
-
});
|
|
1094
|
-
await debug?.log("SUBMIT", "SUBMIT_THIRD_PARTY_RESULT", {
|
|
1095
|
-
messageId: result.messageId
|
|
1096
|
-
});
|
|
1097
|
-
return ok("is-call-return");
|
|
1098
|
-
} else {
|
|
1099
|
-
return ok("continue-workflow");
|
|
1312
|
+
getPlanStep(concurrent, targetStep) {
|
|
1313
|
+
return {
|
|
1314
|
+
stepId: 0,
|
|
1315
|
+
stepName: this.stepName,
|
|
1316
|
+
stepType: this.stepType,
|
|
1317
|
+
concurrent,
|
|
1318
|
+
targetStep
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
async getResultStep(concurrent, stepId) {
|
|
1322
|
+
let result = this.stepFunction();
|
|
1323
|
+
if (result instanceof Promise) {
|
|
1324
|
+
result = await result;
|
|
1100
1325
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1326
|
+
return {
|
|
1327
|
+
stepId,
|
|
1328
|
+
stepName: this.stepName,
|
|
1329
|
+
stepType: this.stepType,
|
|
1330
|
+
out: result,
|
|
1331
|
+
concurrent
|
|
1332
|
+
};
|
|
1106
1333
|
}
|
|
1107
1334
|
};
|
|
1108
|
-
var
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
};
|
|
1115
|
-
var getHeaders = ({
|
|
1116
|
-
initHeaderValue,
|
|
1117
|
-
workflowRunId,
|
|
1118
|
-
workflowUrl,
|
|
1119
|
-
userHeaders,
|
|
1120
|
-
failureUrl,
|
|
1121
|
-
retries,
|
|
1122
|
-
step,
|
|
1123
|
-
callRetries,
|
|
1124
|
-
callTimeout,
|
|
1125
|
-
telemetry
|
|
1126
|
-
}) => {
|
|
1127
|
-
const baseHeaders = {
|
|
1128
|
-
[WORKFLOW_INIT_HEADER]: initHeaderValue,
|
|
1129
|
-
[WORKFLOW_ID_HEADER]: workflowRunId,
|
|
1130
|
-
[WORKFLOW_URL_HEADER]: workflowUrl,
|
|
1131
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1132
|
-
...telemetry ? getTelemetryHeaders(telemetry) : {}
|
|
1133
|
-
};
|
|
1134
|
-
if (!step?.callUrl) {
|
|
1135
|
-
baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1335
|
+
var LazySleepStep = class extends BaseLazyStep {
|
|
1336
|
+
sleep;
|
|
1337
|
+
stepType = "SleepFor";
|
|
1338
|
+
constructor(stepName, sleep) {
|
|
1339
|
+
super(stepName);
|
|
1340
|
+
this.sleep = sleep;
|
|
1136
1341
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1342
|
+
getPlanStep(concurrent, targetStep) {
|
|
1343
|
+
return {
|
|
1344
|
+
stepId: 0,
|
|
1345
|
+
stepName: this.stepName,
|
|
1346
|
+
stepType: this.stepType,
|
|
1347
|
+
sleepFor: this.sleep,
|
|
1348
|
+
concurrent,
|
|
1349
|
+
targetStep
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
async getResultStep(concurrent, stepId) {
|
|
1353
|
+
return await Promise.resolve({
|
|
1354
|
+
stepId,
|
|
1355
|
+
stepName: this.stepName,
|
|
1356
|
+
stepType: this.stepType,
|
|
1357
|
+
sleepFor: this.sleep,
|
|
1358
|
+
concurrent
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
var LazySleepUntilStep = class extends BaseLazyStep {
|
|
1363
|
+
sleepUntil;
|
|
1364
|
+
stepType = "SleepUntil";
|
|
1365
|
+
constructor(stepName, sleepUntil) {
|
|
1366
|
+
super(stepName);
|
|
1367
|
+
this.sleepUntil = sleepUntil;
|
|
1139
1368
|
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
}
|
|
1150
|
-
if (!step?.callUrl) {
|
|
1151
|
-
baseHeaders["Upstash-Failure-Callback"] = failureUrl;
|
|
1152
|
-
}
|
|
1369
|
+
getPlanStep(concurrent, targetStep) {
|
|
1370
|
+
return {
|
|
1371
|
+
stepId: 0,
|
|
1372
|
+
stepName: this.stepName,
|
|
1373
|
+
stepType: this.stepType,
|
|
1374
|
+
sleepUntil: this.sleepUntil,
|
|
1375
|
+
concurrent,
|
|
1376
|
+
targetStep
|
|
1377
|
+
};
|
|
1153
1378
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
baseHeaders["Upstash-Retries"] = retries.toString();
|
|
1163
|
-
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1379
|
+
async getResultStep(concurrent, stepId) {
|
|
1380
|
+
return await Promise.resolve({
|
|
1381
|
+
stepId,
|
|
1382
|
+
stepName: this.stepName,
|
|
1383
|
+
stepType: this.stepType,
|
|
1384
|
+
sleepUntil: this.sleepUntil,
|
|
1385
|
+
concurrent
|
|
1386
|
+
});
|
|
1164
1387
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1388
|
+
};
|
|
1389
|
+
var LazyCallStep = class extends BaseLazyStep {
|
|
1390
|
+
url;
|
|
1391
|
+
method;
|
|
1392
|
+
body;
|
|
1393
|
+
headers;
|
|
1394
|
+
retries;
|
|
1395
|
+
timeout;
|
|
1396
|
+
flowControl;
|
|
1397
|
+
stepType = "Call";
|
|
1398
|
+
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
1399
|
+
super(stepName);
|
|
1400
|
+
this.url = url;
|
|
1401
|
+
this.method = method;
|
|
1402
|
+
this.body = body;
|
|
1403
|
+
this.headers = headers;
|
|
1404
|
+
this.retries = retries;
|
|
1405
|
+
this.timeout = timeout;
|
|
1406
|
+
this.flowControl = flowControl;
|
|
1174
1407
|
}
|
|
1175
|
-
|
|
1176
|
-
if (step?.callHeaders) {
|
|
1177
|
-
const forwardedHeaders = Object.fromEntries(
|
|
1178
|
-
Object.entries(step.callHeaders).map(([header, value]) => [
|
|
1179
|
-
`Upstash-Forward-${header}`,
|
|
1180
|
-
value
|
|
1181
|
-
])
|
|
1182
|
-
);
|
|
1408
|
+
getPlanStep(concurrent, targetStep) {
|
|
1183
1409
|
return {
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1190
|
-
"Upstash-Callback-Workflow-Init": "false",
|
|
1191
|
-
"Upstash-Callback-Workflow-Url": workflowUrl,
|
|
1192
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1193
|
-
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1194
|
-
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1195
|
-
"Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
|
|
1196
|
-
"Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
|
|
1197
|
-
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
1198
|
-
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
1199
|
-
"Upstash-Workflow-CallType": "toCallback"
|
|
1200
|
-
}
|
|
1410
|
+
stepId: 0,
|
|
1411
|
+
stepName: this.stepName,
|
|
1412
|
+
stepType: this.stepType,
|
|
1413
|
+
concurrent,
|
|
1414
|
+
targetStep
|
|
1201
1415
|
};
|
|
1202
1416
|
}
|
|
1203
|
-
|
|
1417
|
+
async getResultStep(concurrent, stepId) {
|
|
1418
|
+
return await Promise.resolve({
|
|
1419
|
+
stepId,
|
|
1420
|
+
stepName: this.stepName,
|
|
1421
|
+
stepType: this.stepType,
|
|
1422
|
+
concurrent,
|
|
1423
|
+
callUrl: this.url,
|
|
1424
|
+
callMethod: this.method,
|
|
1425
|
+
callBody: this.body,
|
|
1426
|
+
callHeaders: this.headers
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
var LazyWaitForEventStep = class extends BaseLazyStep {
|
|
1431
|
+
eventId;
|
|
1432
|
+
timeout;
|
|
1433
|
+
stepType = "Wait";
|
|
1434
|
+
constructor(stepName, eventId, timeout) {
|
|
1435
|
+
super(stepName);
|
|
1436
|
+
this.eventId = eventId;
|
|
1437
|
+
this.timeout = timeout;
|
|
1438
|
+
}
|
|
1439
|
+
getPlanStep(concurrent, targetStep) {
|
|
1204
1440
|
return {
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
|
|
1213
|
-
),
|
|
1214
|
-
// to include telemetry headers:
|
|
1215
|
-
...telemetry ? Object.fromEntries(
|
|
1216
|
-
Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
|
|
1217
|
-
header,
|
|
1218
|
-
[value]
|
|
1219
|
-
])
|
|
1220
|
-
) : {},
|
|
1221
|
-
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
1222
|
-
"Upstash-Workflow-Runid": [workflowRunId],
|
|
1223
|
-
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
1224
|
-
[WORKFLOW_URL_HEADER]: [workflowUrl],
|
|
1225
|
-
"Upstash-Workflow-CallType": ["step"],
|
|
1226
|
-
"Content-Type": [contentType]
|
|
1227
|
-
}
|
|
1441
|
+
stepId: 0,
|
|
1442
|
+
stepName: this.stepName,
|
|
1443
|
+
stepType: this.stepType,
|
|
1444
|
+
waitEventId: this.eventId,
|
|
1445
|
+
timeout: this.timeout,
|
|
1446
|
+
concurrent,
|
|
1447
|
+
targetStep
|
|
1228
1448
|
};
|
|
1229
1449
|
}
|
|
1230
|
-
|
|
1450
|
+
async getResultStep(concurrent, stepId) {
|
|
1451
|
+
return await Promise.resolve({
|
|
1452
|
+
stepId,
|
|
1453
|
+
stepName: this.stepName,
|
|
1454
|
+
stepType: this.stepType,
|
|
1455
|
+
waitEventId: this.eventId,
|
|
1456
|
+
timeout: this.timeout,
|
|
1457
|
+
concurrent
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1231
1460
|
};
|
|
1232
|
-
var
|
|
1233
|
-
|
|
1234
|
-
|
|
1461
|
+
var LazyNotifyStep = class extends LazyFunctionStep {
|
|
1462
|
+
stepType = "Notify";
|
|
1463
|
+
constructor(stepName, eventId, eventData, requester) {
|
|
1464
|
+
super(stepName, async () => {
|
|
1465
|
+
const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
|
|
1466
|
+
return {
|
|
1467
|
+
eventId,
|
|
1468
|
+
eventData,
|
|
1469
|
+
notifyResponse
|
|
1470
|
+
};
|
|
1471
|
+
});
|
|
1235
1472
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1473
|
+
};
|
|
1474
|
+
var LazyInvokeStep = class extends BaseLazyStep {
|
|
1475
|
+
stepType = "Invoke";
|
|
1476
|
+
params;
|
|
1477
|
+
constructor(stepName, {
|
|
1478
|
+
workflow,
|
|
1479
|
+
body,
|
|
1480
|
+
headers = {},
|
|
1481
|
+
workflowRunId,
|
|
1482
|
+
retries,
|
|
1483
|
+
flowControl
|
|
1484
|
+
}) {
|
|
1485
|
+
super(stepName);
|
|
1486
|
+
this.params = {
|
|
1487
|
+
workflow,
|
|
1241
1488
|
body,
|
|
1242
|
-
|
|
1489
|
+
headers,
|
|
1490
|
+
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1491
|
+
retries,
|
|
1492
|
+
flowControl
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
getPlanStep(concurrent, targetStep) {
|
|
1496
|
+
return {
|
|
1497
|
+
stepId: 0,
|
|
1498
|
+
stepName: this.stepName,
|
|
1499
|
+
stepType: this.stepType,
|
|
1500
|
+
concurrent,
|
|
1501
|
+
targetStep
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* won't be used as it's the server who will add the result step
|
|
1506
|
+
* in Invoke step.
|
|
1507
|
+
*/
|
|
1508
|
+
getResultStep(concurrent, stepId) {
|
|
1509
|
+
return Promise.resolve({
|
|
1510
|
+
stepId,
|
|
1511
|
+
stepName: this.stepName,
|
|
1512
|
+
stepType: this.stepType,
|
|
1513
|
+
concurrent
|
|
1243
1514
|
});
|
|
1244
|
-
if (!isValid) {
|
|
1245
|
-
throw new Error("Signature in `Upstash-Signature` header is not valid");
|
|
1246
|
-
}
|
|
1247
|
-
} catch (error) {
|
|
1248
|
-
throw new WorkflowError(
|
|
1249
|
-
`Failed to verify that the Workflow request comes from QStash: ${error}
|
|
1250
|
-
|
|
1251
|
-
If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
|
|
1252
|
-
|
|
1253
|
-
If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
|
|
1254
|
-
);
|
|
1255
1515
|
}
|
|
1256
1516
|
};
|
|
1257
1517
|
|
|
@@ -1265,14 +1525,16 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1265
1525
|
nonPlanStepCount;
|
|
1266
1526
|
steps;
|
|
1267
1527
|
indexInCurrentList = 0;
|
|
1528
|
+
invokeCount;
|
|
1268
1529
|
telemetry;
|
|
1269
1530
|
stepCount = 0;
|
|
1270
1531
|
planStepCount = 0;
|
|
1271
1532
|
executingStep = false;
|
|
1272
|
-
constructor(context, steps, telemetry, debug) {
|
|
1533
|
+
constructor(context, steps, telemetry, invokeCount, debug) {
|
|
1273
1534
|
this.context = context;
|
|
1274
1535
|
this.steps = steps;
|
|
1275
1536
|
this.telemetry = telemetry;
|
|
1537
|
+
this.invokeCount = invokeCount ?? 0;
|
|
1276
1538
|
this.debug = debug;
|
|
1277
1539
|
this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
|
|
1278
1540
|
}
|
|
@@ -1495,7 +1757,9 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1495
1757
|
step: waitStep,
|
|
1496
1758
|
failureUrl: this.context.failureUrl,
|
|
1497
1759
|
retries: this.context.retries,
|
|
1498
|
-
telemetry: this.telemetry
|
|
1760
|
+
telemetry: this.telemetry,
|
|
1761
|
+
invokeCount: this.invokeCount,
|
|
1762
|
+
flowControl: this.context.flowControl
|
|
1499
1763
|
});
|
|
1500
1764
|
const waitBody = {
|
|
1501
1765
|
url: this.context.url,
|
|
@@ -1518,7 +1782,19 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1518
1782
|
method: "POST",
|
|
1519
1783
|
parseResponseAsJson: false
|
|
1520
1784
|
});
|
|
1521
|
-
throw new WorkflowAbort(
|
|
1785
|
+
throw new WorkflowAbort(waitStep.stepName, waitStep);
|
|
1786
|
+
}
|
|
1787
|
+
if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
|
|
1788
|
+
const invokeStep = steps[0];
|
|
1789
|
+
const lazyInvokeStep = lazySteps[0];
|
|
1790
|
+
await invokeWorkflow({
|
|
1791
|
+
settings: lazyInvokeStep.params,
|
|
1792
|
+
invokeStep,
|
|
1793
|
+
context: this.context,
|
|
1794
|
+
invokeCount: this.invokeCount,
|
|
1795
|
+
telemetry: this.telemetry
|
|
1796
|
+
});
|
|
1797
|
+
throw new WorkflowAbort(invokeStep.stepName, invokeStep);
|
|
1522
1798
|
}
|
|
1523
1799
|
const result = await this.context.qstashClient.batchJSON(
|
|
1524
1800
|
steps.map((singleStep, index) => {
|
|
@@ -1533,11 +1809,14 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1533
1809
|
retries: this.context.retries,
|
|
1534
1810
|
callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
|
|
1535
1811
|
callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
|
|
1536
|
-
telemetry: this.telemetry
|
|
1812
|
+
telemetry: this.telemetry,
|
|
1813
|
+
invokeCount: this.invokeCount,
|
|
1814
|
+
flowControl: this.context.flowControl,
|
|
1815
|
+
callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
|
|
1537
1816
|
});
|
|
1538
1817
|
const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
|
|
1539
1818
|
singleStep.out = JSON.stringify(singleStep.out);
|
|
1540
|
-
return singleStep.callUrl ? (
|
|
1819
|
+
return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
|
|
1541
1820
|
// if the step is a third party call, we call the third party
|
|
1542
1821
|
// url (singleStep.callUrl) and pass information about the workflow
|
|
1543
1822
|
// in the headers (handled in getHeaders). QStash makes the request
|
|
@@ -2101,6 +2380,11 @@ var WorkflowContext = class {
|
|
|
2101
2380
|
* Number of retries
|
|
2102
2381
|
*/
|
|
2103
2382
|
retries;
|
|
2383
|
+
/**
|
|
2384
|
+
* Settings for controlling the number of active requests
|
|
2385
|
+
* and number of requests per second with the same key.
|
|
2386
|
+
*/
|
|
2387
|
+
flowControl;
|
|
2104
2388
|
constructor({
|
|
2105
2389
|
qstashClient,
|
|
2106
2390
|
workflowRunId,
|
|
@@ -2112,7 +2396,9 @@ var WorkflowContext = class {
|
|
|
2112
2396
|
initialPayload,
|
|
2113
2397
|
env,
|
|
2114
2398
|
retries,
|
|
2115
|
-
telemetry
|
|
2399
|
+
telemetry,
|
|
2400
|
+
invokeCount,
|
|
2401
|
+
flowControl
|
|
2116
2402
|
}) {
|
|
2117
2403
|
this.qstashClient = qstashClient;
|
|
2118
2404
|
this.workflowRunId = workflowRunId;
|
|
@@ -2123,7 +2409,8 @@ var WorkflowContext = class {
|
|
|
2123
2409
|
this.requestPayload = initialPayload;
|
|
2124
2410
|
this.env = env ?? {};
|
|
2125
2411
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2126
|
-
this.
|
|
2412
|
+
this.flowControl = flowControl;
|
|
2413
|
+
this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
|
|
2127
2414
|
}
|
|
2128
2415
|
/**
|
|
2129
2416
|
* Executes a workflow step
|
|
@@ -2225,7 +2512,7 @@ var WorkflowContext = class {
|
|
|
2225
2512
|
* }
|
|
2226
2513
|
*/
|
|
2227
2514
|
async call(stepName, settings) {
|
|
2228
|
-
const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
|
|
2515
|
+
const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
|
|
2229
2516
|
const result = await this.addStep(
|
|
2230
2517
|
new LazyCallStep(
|
|
2231
2518
|
stepName,
|
|
@@ -2234,7 +2521,8 @@ var WorkflowContext = class {
|
|
|
2234
2521
|
body,
|
|
2235
2522
|
headers,
|
|
2236
2523
|
retries,
|
|
2237
|
-
timeout
|
|
2524
|
+
timeout,
|
|
2525
|
+
flowControl
|
|
2238
2526
|
)
|
|
2239
2527
|
);
|
|
2240
2528
|
if (typeof result === "string") {
|
|
@@ -2343,6 +2631,13 @@ var WorkflowContext = class {
|
|
|
2343
2631
|
return result;
|
|
2344
2632
|
}
|
|
2345
2633
|
}
|
|
2634
|
+
async invoke(stepName, settings) {
|
|
2635
|
+
const result = await this.addStep(new LazyInvokeStep(stepName, settings));
|
|
2636
|
+
return {
|
|
2637
|
+
...result,
|
|
2638
|
+
body: result.body ? JSON.parse(result.body) : void 0
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2346
2641
|
/**
|
|
2347
2642
|
* Cancel the current workflow run
|
|
2348
2643
|
*
|
|
@@ -2420,31 +2715,6 @@ var WorkflowLogger = class _WorkflowLogger {
|
|
|
2420
2715
|
}
|
|
2421
2716
|
};
|
|
2422
2717
|
|
|
2423
|
-
// src/utils.ts
|
|
2424
|
-
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
2425
|
-
var NANOID_LENGTH = 21;
|
|
2426
|
-
function getRandomInt() {
|
|
2427
|
-
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
2428
|
-
}
|
|
2429
|
-
function nanoid() {
|
|
2430
|
-
return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
|
|
2431
|
-
}
|
|
2432
|
-
function getWorkflowRunId(id) {
|
|
2433
|
-
return `wfr_${id ?? nanoid()}`;
|
|
2434
|
-
}
|
|
2435
|
-
function decodeBase64(base64) {
|
|
2436
|
-
try {
|
|
2437
|
-
const binString = atob(base64);
|
|
2438
|
-
const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
2439
|
-
return new TextDecoder().decode(intArray);
|
|
2440
|
-
} catch (error) {
|
|
2441
|
-
console.warn(
|
|
2442
|
-
`Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
|
|
2443
|
-
);
|
|
2444
|
-
return atob(base64);
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
|
-
|
|
2448
2718
|
// src/serve/authorization.ts
|
|
2449
2719
|
import { Client as Client2 } from "@upstash/qstash";
|
|
2450
2720
|
var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
|
|
@@ -2489,7 +2759,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2489
2759
|
failureUrl: context.failureUrl,
|
|
2490
2760
|
initialPayload: context.requestPayload,
|
|
2491
2761
|
env: context.env,
|
|
2492
|
-
retries: context.retries
|
|
2762
|
+
retries: context.retries,
|
|
2763
|
+
flowControl: context.flowControl
|
|
2493
2764
|
});
|
|
2494
2765
|
try {
|
|
2495
2766
|
await routeFunction(disabledContext);
|
|
@@ -2642,7 +2913,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2642
2913
|
};
|
|
2643
2914
|
}
|
|
2644
2915
|
};
|
|
2645
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
|
|
2916
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
2646
2917
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
2647
2918
|
return ok("not-failure-callback");
|
|
2648
2919
|
}
|
|
@@ -2654,22 +2925,21 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
2654
2925
|
);
|
|
2655
2926
|
}
|
|
2656
2927
|
try {
|
|
2657
|
-
const { status, header, body, url,
|
|
2658
|
-
requestPayload
|
|
2659
|
-
);
|
|
2928
|
+
const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
|
|
2660
2929
|
const decodedBody = body ? decodeBase64(body) : "{}";
|
|
2661
2930
|
const errorPayload = JSON.parse(decodedBody);
|
|
2662
2931
|
const workflowContext = new WorkflowContext({
|
|
2663
2932
|
qstashClient,
|
|
2664
2933
|
workflowRunId,
|
|
2665
2934
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
2666
|
-
headers: recreateUserHeaders(
|
|
2935
|
+
headers: recreateUserHeaders(request.headers),
|
|
2667
2936
|
steps: [],
|
|
2668
2937
|
url,
|
|
2669
2938
|
failureUrl: url,
|
|
2670
2939
|
debug,
|
|
2671
2940
|
env,
|
|
2672
2941
|
retries,
|
|
2942
|
+
flowControl,
|
|
2673
2943
|
telemetry: void 0
|
|
2674
2944
|
// not going to make requests in authentication check
|
|
2675
2945
|
});
|
|
@@ -2796,7 +3066,8 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2796
3066
|
env,
|
|
2797
3067
|
retries,
|
|
2798
3068
|
useJSONContent,
|
|
2799
|
-
disableTelemetry
|
|
3069
|
+
disableTelemetry,
|
|
3070
|
+
flowControl
|
|
2800
3071
|
} = processOptions(options);
|
|
2801
3072
|
telemetry = disableTelemetry ? void 0 : telemetry;
|
|
2802
3073
|
const debug = WorkflowLogger.getLogger(verbose);
|
|
@@ -2837,6 +3108,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2837
3108
|
failureFunction,
|
|
2838
3109
|
env,
|
|
2839
3110
|
retries,
|
|
3111
|
+
flowControl,
|
|
2840
3112
|
debug
|
|
2841
3113
|
);
|
|
2842
3114
|
if (failureCheck.isErr()) {
|
|
@@ -2845,6 +3117,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2845
3117
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
2846
3118
|
return onStepFinish(workflowRunId, "failure-callback");
|
|
2847
3119
|
}
|
|
3120
|
+
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
2848
3121
|
const workflowContext = new WorkflowContext({
|
|
2849
3122
|
qstashClient,
|
|
2850
3123
|
workflowRunId,
|
|
@@ -2856,7 +3129,9 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2856
3129
|
debug,
|
|
2857
3130
|
env,
|
|
2858
3131
|
retries,
|
|
2859
|
-
telemetry
|
|
3132
|
+
telemetry,
|
|
3133
|
+
invokeCount,
|
|
3134
|
+
flowControl
|
|
2860
3135
|
});
|
|
2861
3136
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
2862
3137
|
routeFunction,
|
|
@@ -2879,6 +3154,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2879
3154
|
workflowUrl,
|
|
2880
3155
|
failureUrl: workflowFailureUrl,
|
|
2881
3156
|
retries,
|
|
3157
|
+
flowControl,
|
|
2882
3158
|
telemetry,
|
|
2883
3159
|
debug
|
|
2884
3160
|
});
|
|
@@ -2888,10 +3164,16 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2888
3164
|
});
|
|
2889
3165
|
throw callReturnCheck.error;
|
|
2890
3166
|
} else if (callReturnCheck.value === "continue-workflow") {
|
|
2891
|
-
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3167
|
+
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3168
|
+
workflowContext,
|
|
3169
|
+
useJSONContent,
|
|
3170
|
+
telemetry,
|
|
3171
|
+
debug,
|
|
3172
|
+
invokeCount
|
|
3173
|
+
}) : await triggerRouteFunction({
|
|
2892
3174
|
onStep: async () => routeFunction(workflowContext),
|
|
2893
|
-
onCleanup: async () => {
|
|
2894
|
-
await triggerWorkflowDelete(workflowContext, debug);
|
|
3175
|
+
onCleanup: async (result2) => {
|
|
3176
|
+
await triggerWorkflowDelete(workflowContext, result2, debug);
|
|
2895
3177
|
},
|
|
2896
3178
|
onCancel: async () => {
|
|
2897
3179
|
await makeCancelRequest(workflowContext.qstashClient.http, workflowRunId);
|
|
@@ -2942,12 +3224,13 @@ export {
|
|
|
2942
3224
|
SDK_TELEMETRY,
|
|
2943
3225
|
WorkflowError,
|
|
2944
3226
|
WorkflowAbort,
|
|
3227
|
+
getWorkflowRunId,
|
|
2945
3228
|
StepTypes,
|
|
2946
3229
|
triggerFirstInvocation,
|
|
3230
|
+
serveManyBase,
|
|
2947
3231
|
WorkflowTool,
|
|
2948
3232
|
WorkflowContext,
|
|
2949
3233
|
WorkflowLogger,
|
|
2950
|
-
getWorkflowRunId,
|
|
2951
3234
|
serveBase,
|
|
2952
3235
|
serve
|
|
2953
3236
|
};
|