@upstash/workflow 0.2.8-rc-invoke → 0.2.9
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 +4 -4
- package/astro.d.ts +4 -4
- package/astro.js +282 -135
- package/astro.mjs +17 -15
- package/{chunk-IWAW7GIG.mjs → chunk-IPXJZU3K.mjs} +851 -592
- package/cloudflare.d.mts +4 -4
- package/cloudflare.d.ts +4 -4
- package/cloudflare.js +278 -135
- package/cloudflare.mjs +13 -15
- package/express.d.mts +4 -4
- package/express.d.ts +4 -4
- package/express.js +281 -144
- package/express.mjs +16 -22
- package/h3.d.mts +4 -4
- package/h3.d.ts +4 -4
- package/h3.js +275 -135
- package/h3.mjs +10 -15
- package/hono.d.mts +4 -4
- package/hono.d.ts +4 -4
- package/hono.js +277 -134
- package/hono.mjs +12 -14
- package/index.d.mts +268 -5
- package/index.d.ts +268 -5
- package/index.js +297 -43
- package/index.mjs +60 -3
- package/nextjs.d.mts +6 -6
- package/nextjs.d.ts +6 -6
- package/nextjs.js +286 -143
- package/nextjs.mjs +21 -23
- 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 +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +207 -41
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +8 -9
- package/svelte.d.ts +8 -9
- package/svelte.js +278 -135
- package/svelte.mjs +13 -15
- package/{types-C7Y7WUQd.d.mts → types-CYhDXnf8.d.mts} +110 -18
- package/{types-C7Y7WUQd.d.ts → types-CYhDXnf8.d.ts} +110 -18
- package/chunk-LCZMBGEM.mjs +0 -95
- package/serve-many-BlBvXfBS.d.mts +0 -10
- package/serve-many-Dw-UUnH6.d.ts +0 -10
package/astro.js
CHANGED
|
@@ -85,6 +85,7 @@ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
|
|
|
85
85
|
var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
86
86
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
87
87
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
88
|
+
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
88
89
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
89
90
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
90
91
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
@@ -266,8 +267,9 @@ var LazyCallStep = class extends BaseLazyStep {
|
|
|
266
267
|
headers;
|
|
267
268
|
retries;
|
|
268
269
|
timeout;
|
|
270
|
+
flowControl;
|
|
269
271
|
stepType = "Call";
|
|
270
|
-
constructor(stepName, url, method, body, headers, retries, timeout) {
|
|
272
|
+
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
271
273
|
super(stepName);
|
|
272
274
|
this.url = url;
|
|
273
275
|
this.method = method;
|
|
@@ -275,6 +277,7 @@ var LazyCallStep = class extends BaseLazyStep {
|
|
|
275
277
|
this.headers = headers;
|
|
276
278
|
this.retries = retries;
|
|
277
279
|
this.timeout = timeout;
|
|
280
|
+
this.flowControl = flowControl;
|
|
278
281
|
}
|
|
279
282
|
getPlanStep(concurrent, targetStep) {
|
|
280
283
|
return {
|
|
@@ -345,14 +348,22 @@ var LazyNotifyStep = class extends LazyFunctionStep {
|
|
|
345
348
|
var LazyInvokeStep = class extends BaseLazyStep {
|
|
346
349
|
stepType = "Invoke";
|
|
347
350
|
params;
|
|
348
|
-
constructor(stepName, {
|
|
351
|
+
constructor(stepName, {
|
|
352
|
+
workflow,
|
|
353
|
+
body,
|
|
354
|
+
headers = {},
|
|
355
|
+
workflowRunId,
|
|
356
|
+
retries,
|
|
357
|
+
flowControl
|
|
358
|
+
}) {
|
|
349
359
|
super(stepName);
|
|
350
360
|
this.params = {
|
|
351
361
|
workflow,
|
|
352
362
|
body,
|
|
353
363
|
headers,
|
|
354
364
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
355
|
-
retries
|
|
365
|
+
retries,
|
|
366
|
+
flowControl
|
|
356
367
|
};
|
|
357
368
|
}
|
|
358
369
|
getPlanStep(concurrent, targetStep) {
|
|
@@ -811,7 +822,8 @@ var triggerFirstInvocation = async ({
|
|
|
811
822
|
workflowContext,
|
|
812
823
|
useJSONContent,
|
|
813
824
|
telemetry: telemetry2,
|
|
814
|
-
debug
|
|
825
|
+
debug,
|
|
826
|
+
invokeCount
|
|
815
827
|
}) => {
|
|
816
828
|
const { headers } = getHeaders({
|
|
817
829
|
initHeaderValue: "true",
|
|
@@ -820,7 +832,9 @@ var triggerFirstInvocation = async ({
|
|
|
820
832
|
userHeaders: workflowContext.headers,
|
|
821
833
|
failureUrl: workflowContext.failureUrl,
|
|
822
834
|
retries: workflowContext.retries,
|
|
823
|
-
telemetry: telemetry2
|
|
835
|
+
telemetry: telemetry2,
|
|
836
|
+
invokeCount,
|
|
837
|
+
flowControl: workflowContext.flowControl
|
|
824
838
|
});
|
|
825
839
|
if (workflowContext.headers.get("content-type")) {
|
|
826
840
|
headers["content-type"] = workflowContext.headers.get("content-type");
|
|
@@ -926,6 +940,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
926
940
|
failureUrl,
|
|
927
941
|
retries,
|
|
928
942
|
telemetry: telemetry2,
|
|
943
|
+
flowControl,
|
|
929
944
|
debug
|
|
930
945
|
}) => {
|
|
931
946
|
try {
|
|
@@ -973,6 +988,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
973
988
|
const stepType = request.headers.get("Upstash-Workflow-StepType");
|
|
974
989
|
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
975
990
|
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
991
|
+
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
976
992
|
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
977
993
|
throw new Error(
|
|
978
994
|
`Missing info in callback message source header: ${JSON.stringify({
|
|
@@ -993,7 +1009,9 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
993
1009
|
userHeaders,
|
|
994
1010
|
failureUrl,
|
|
995
1011
|
retries,
|
|
996
|
-
telemetry: telemetry2
|
|
1012
|
+
telemetry: telemetry2,
|
|
1013
|
+
invokeCount: Number(invokeCount),
|
|
1014
|
+
flowControl
|
|
997
1015
|
});
|
|
998
1016
|
const callResponse = {
|
|
999
1017
|
status: callbackMessage.status,
|
|
@@ -1049,7 +1067,10 @@ var getHeaders = ({
|
|
|
1049
1067
|
step,
|
|
1050
1068
|
callRetries,
|
|
1051
1069
|
callTimeout,
|
|
1052
|
-
telemetry: telemetry2
|
|
1070
|
+
telemetry: telemetry2,
|
|
1071
|
+
invokeCount,
|
|
1072
|
+
flowControl,
|
|
1073
|
+
callFlowControl
|
|
1053
1074
|
}) => {
|
|
1054
1075
|
const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
1055
1076
|
const baseHeaders = {
|
|
@@ -1061,6 +1082,9 @@ var getHeaders = ({
|
|
|
1061
1082
|
"content-type": contentType,
|
|
1062
1083
|
...telemetry2 ? getTelemetryHeaders(telemetry2) : {}
|
|
1063
1084
|
};
|
|
1085
|
+
if (invokeCount !== void 0 && !step?.callUrl) {
|
|
1086
|
+
baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
|
|
1087
|
+
}
|
|
1064
1088
|
if (!step?.callUrl) {
|
|
1065
1089
|
baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1066
1090
|
}
|
|
@@ -1069,13 +1093,23 @@ var getHeaders = ({
|
|
|
1069
1093
|
}
|
|
1070
1094
|
if (failureUrl) {
|
|
1071
1095
|
baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
|
|
1096
|
+
baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
|
|
1097
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
|
|
1098
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
|
|
1099
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
|
|
1100
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
|
|
1101
|
+
if (retries !== void 0) {
|
|
1102
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1103
|
+
}
|
|
1104
|
+
if (flowControl) {
|
|
1105
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1106
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
|
|
1107
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
|
|
1108
|
+
}
|
|
1072
1109
|
if (!step?.callUrl) {
|
|
1073
1110
|
baseHeaders["Upstash-Failure-Callback"] = failureUrl;
|
|
1074
1111
|
}
|
|
1075
1112
|
}
|
|
1076
|
-
if (step?.stepType === "Invoke") {
|
|
1077
|
-
baseHeaders["upstash-workflow-invoke"] = "true";
|
|
1078
|
-
}
|
|
1079
1113
|
if (step?.callUrl) {
|
|
1080
1114
|
baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
|
|
1081
1115
|
baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
@@ -1083,9 +1117,26 @@ var getHeaders = ({
|
|
|
1083
1117
|
baseHeaders["Upstash-Callback-Retries"] = retries.toString();
|
|
1084
1118
|
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1085
1119
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1120
|
+
if (callFlowControl) {
|
|
1121
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
|
|
1122
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1123
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1124
|
+
}
|
|
1125
|
+
if (flowControl) {
|
|
1126
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1127
|
+
baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
|
|
1128
|
+
baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
|
|
1129
|
+
}
|
|
1130
|
+
} else {
|
|
1131
|
+
if (flowControl) {
|
|
1132
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1133
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1134
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1135
|
+
}
|
|
1136
|
+
if (retries !== void 0) {
|
|
1137
|
+
baseHeaders["Upstash-Retries"] = retries.toString();
|
|
1138
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1139
|
+
}
|
|
1089
1140
|
}
|
|
1090
1141
|
if (userHeaders) {
|
|
1091
1142
|
for (const header of userHeaders.keys()) {
|
|
@@ -1120,6 +1171,7 @@ var getHeaders = ({
|
|
|
1120
1171
|
"Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
|
|
1121
1172
|
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
1122
1173
|
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
1174
|
+
[`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
|
|
1123
1175
|
"Upstash-Workflow-CallType": "toCallback"
|
|
1124
1176
|
}
|
|
1125
1177
|
};
|
|
@@ -1177,9 +1229,159 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
|
|
|
1177
1229
|
);
|
|
1178
1230
|
}
|
|
1179
1231
|
};
|
|
1232
|
+
var prepareFlowControl = (flowControl) => {
|
|
1233
|
+
const parallelism = flowControl.parallelism?.toString();
|
|
1234
|
+
const rate = flowControl.ratePerSecond?.toString();
|
|
1235
|
+
const controlValue = [
|
|
1236
|
+
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
1237
|
+
rate ? `rate=${rate}` : void 0
|
|
1238
|
+
].filter(Boolean);
|
|
1239
|
+
if (controlValue.length === 0) {
|
|
1240
|
+
throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
1241
|
+
}
|
|
1242
|
+
return {
|
|
1243
|
+
flowControlKey: flowControl.key,
|
|
1244
|
+
flowControlValue: controlValue.join(", ")
|
|
1245
|
+
};
|
|
1246
|
+
};
|
|
1180
1247
|
|
|
1181
1248
|
// src/context/auto-executor.ts
|
|
1182
1249
|
var import_qstash4 = require("@upstash/qstash");
|
|
1250
|
+
|
|
1251
|
+
// src/serve/serve-many.ts
|
|
1252
|
+
var getWorkflowId = (url) => {
|
|
1253
|
+
const components = url.split("/");
|
|
1254
|
+
const lastComponent = components[components.length - 1];
|
|
1255
|
+
return lastComponent.split("?")[0];
|
|
1256
|
+
};
|
|
1257
|
+
var serveManyBase = ({
|
|
1258
|
+
workflows,
|
|
1259
|
+
getUrl,
|
|
1260
|
+
serveMethod,
|
|
1261
|
+
options
|
|
1262
|
+
}) => {
|
|
1263
|
+
const workflowIds = [];
|
|
1264
|
+
const workflowMap = Object.fromEntries(
|
|
1265
|
+
Object.entries(workflows).map((workflow) => {
|
|
1266
|
+
const workflowId = workflow[0];
|
|
1267
|
+
if (workflowIds.includes(workflowId)) {
|
|
1268
|
+
throw new WorkflowError(
|
|
1269
|
+
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
if (workflowId.includes("/")) {
|
|
1273
|
+
throw new WorkflowError(
|
|
1274
|
+
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
workflowIds.push(workflowId);
|
|
1278
|
+
workflow[1].workflowId = workflowId;
|
|
1279
|
+
workflow[1].options = {
|
|
1280
|
+
...options,
|
|
1281
|
+
...workflow[1].options
|
|
1282
|
+
};
|
|
1283
|
+
const params = [workflow[1].routeFunction, workflow[1].options];
|
|
1284
|
+
const handler = serveMethod(...params);
|
|
1285
|
+
return [workflowId, handler];
|
|
1286
|
+
})
|
|
1287
|
+
);
|
|
1288
|
+
return {
|
|
1289
|
+
handler: async (...params) => {
|
|
1290
|
+
const url = getUrl(...params);
|
|
1291
|
+
const pickedWorkflowId = getWorkflowId(url);
|
|
1292
|
+
if (!pickedWorkflowId) {
|
|
1293
|
+
return new Response(
|
|
1294
|
+
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
1295
|
+
{
|
|
1296
|
+
status: 404
|
|
1297
|
+
}
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
const workflow = workflowMap[pickedWorkflowId];
|
|
1301
|
+
if (!workflow) {
|
|
1302
|
+
return new Response(
|
|
1303
|
+
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
1304
|
+
{
|
|
1305
|
+
status: 404
|
|
1306
|
+
}
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
return await workflow(...params);
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
};
|
|
1313
|
+
var invokeWorkflow = async ({
|
|
1314
|
+
settings,
|
|
1315
|
+
invokeStep,
|
|
1316
|
+
context,
|
|
1317
|
+
invokeCount,
|
|
1318
|
+
telemetry: telemetry2
|
|
1319
|
+
}) => {
|
|
1320
|
+
const {
|
|
1321
|
+
body,
|
|
1322
|
+
workflow,
|
|
1323
|
+
headers = {},
|
|
1324
|
+
workflowRunId = getWorkflowRunId(),
|
|
1325
|
+
retries,
|
|
1326
|
+
flowControl
|
|
1327
|
+
} = settings;
|
|
1328
|
+
const { workflowId } = workflow;
|
|
1329
|
+
const {
|
|
1330
|
+
retries: workflowRetries,
|
|
1331
|
+
failureFunction,
|
|
1332
|
+
failureUrl,
|
|
1333
|
+
useJSONContent,
|
|
1334
|
+
flowControl: workflowFlowControl
|
|
1335
|
+
} = workflow.options;
|
|
1336
|
+
if (!workflowId) {
|
|
1337
|
+
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
1338
|
+
}
|
|
1339
|
+
const { headers: invokerHeaders } = getHeaders({
|
|
1340
|
+
initHeaderValue: "false",
|
|
1341
|
+
workflowRunId: context.workflowRunId,
|
|
1342
|
+
workflowUrl: context.url,
|
|
1343
|
+
userHeaders: context.headers,
|
|
1344
|
+
failureUrl: context.failureUrl,
|
|
1345
|
+
retries: context.retries,
|
|
1346
|
+
telemetry: telemetry2,
|
|
1347
|
+
invokeCount,
|
|
1348
|
+
flowControl: context.flowControl
|
|
1349
|
+
});
|
|
1350
|
+
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1351
|
+
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
1352
|
+
const { headers: triggerHeaders } = getHeaders({
|
|
1353
|
+
initHeaderValue: "true",
|
|
1354
|
+
workflowRunId,
|
|
1355
|
+
workflowUrl: newUrl,
|
|
1356
|
+
userHeaders: new Headers(headers),
|
|
1357
|
+
retries: retries ?? workflowRetries,
|
|
1358
|
+
telemetry: telemetry2,
|
|
1359
|
+
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1360
|
+
invokeCount: invokeCount + 1,
|
|
1361
|
+
flowControl: flowControl ?? workflowFlowControl
|
|
1362
|
+
});
|
|
1363
|
+
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1364
|
+
if (useJSONContent) {
|
|
1365
|
+
triggerHeaders["content-type"] = "application/json";
|
|
1366
|
+
}
|
|
1367
|
+
const request = {
|
|
1368
|
+
body: JSON.stringify(body),
|
|
1369
|
+
headers: Object.fromEntries(
|
|
1370
|
+
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1371
|
+
),
|
|
1372
|
+
workflowRunId,
|
|
1373
|
+
workflowUrl: context.url,
|
|
1374
|
+
step: invokeStep
|
|
1375
|
+
};
|
|
1376
|
+
await context.qstashClient.publish({
|
|
1377
|
+
headers: triggerHeaders,
|
|
1378
|
+
method: "POST",
|
|
1379
|
+
body: JSON.stringify(request),
|
|
1380
|
+
url: newUrl
|
|
1381
|
+
});
|
|
1382
|
+
};
|
|
1383
|
+
|
|
1384
|
+
// src/context/auto-executor.ts
|
|
1183
1385
|
var AutoExecutor = class _AutoExecutor {
|
|
1184
1386
|
context;
|
|
1185
1387
|
promises = /* @__PURE__ */ new WeakMap();
|
|
@@ -1188,14 +1390,16 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1188
1390
|
nonPlanStepCount;
|
|
1189
1391
|
steps;
|
|
1190
1392
|
indexInCurrentList = 0;
|
|
1393
|
+
invokeCount;
|
|
1191
1394
|
telemetry;
|
|
1192
1395
|
stepCount = 0;
|
|
1193
1396
|
planStepCount = 0;
|
|
1194
1397
|
executingStep = false;
|
|
1195
|
-
constructor(context, steps, telemetry2, debug) {
|
|
1398
|
+
constructor(context, steps, telemetry2, invokeCount, debug) {
|
|
1196
1399
|
this.context = context;
|
|
1197
1400
|
this.steps = steps;
|
|
1198
1401
|
this.telemetry = telemetry2;
|
|
1402
|
+
this.invokeCount = invokeCount ?? 0;
|
|
1199
1403
|
this.debug = debug;
|
|
1200
1404
|
this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
|
|
1201
1405
|
}
|
|
@@ -1418,7 +1622,9 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1418
1622
|
step: waitStep,
|
|
1419
1623
|
failureUrl: this.context.failureUrl,
|
|
1420
1624
|
retries: this.context.retries,
|
|
1421
|
-
telemetry: this.telemetry
|
|
1625
|
+
telemetry: this.telemetry,
|
|
1626
|
+
invokeCount: this.invokeCount,
|
|
1627
|
+
flowControl: this.context.flowControl
|
|
1422
1628
|
});
|
|
1423
1629
|
const waitBody = {
|
|
1424
1630
|
url: this.context.url,
|
|
@@ -1446,17 +1652,13 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1446
1652
|
if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
|
|
1447
1653
|
const invokeStep = steps[0];
|
|
1448
1654
|
const lazyInvokeStep = lazySteps[0];
|
|
1449
|
-
await
|
|
1450
|
-
|
|
1451
|
-
body: lazyInvokeStep.params.body,
|
|
1452
|
-
headers: lazyInvokeStep.params.headers,
|
|
1453
|
-
workflowRunId: lazyInvokeStep.params.workflowRunId,
|
|
1454
|
-
workflow: lazyInvokeStep.params.workflow,
|
|
1455
|
-
retries: lazyInvokeStep.params.retries
|
|
1456
|
-
},
|
|
1655
|
+
await invokeWorkflow({
|
|
1656
|
+
settings: lazyInvokeStep.params,
|
|
1457
1657
|
invokeStep,
|
|
1458
|
-
this.context
|
|
1459
|
-
|
|
1658
|
+
context: this.context,
|
|
1659
|
+
invokeCount: this.invokeCount,
|
|
1660
|
+
telemetry: this.telemetry
|
|
1661
|
+
});
|
|
1460
1662
|
throw new WorkflowAbort(invokeStep.stepName, invokeStep);
|
|
1461
1663
|
}
|
|
1462
1664
|
const result = await this.context.qstashClient.batchJSON(
|
|
@@ -1472,11 +1674,14 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1472
1674
|
retries: this.context.retries,
|
|
1473
1675
|
callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
|
|
1474
1676
|
callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
|
|
1475
|
-
telemetry: this.telemetry
|
|
1677
|
+
telemetry: this.telemetry,
|
|
1678
|
+
invokeCount: this.invokeCount,
|
|
1679
|
+
flowControl: this.context.flowControl,
|
|
1680
|
+
callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
|
|
1476
1681
|
});
|
|
1477
1682
|
const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
|
|
1478
1683
|
singleStep.out = JSON.stringify(singleStep.out);
|
|
1479
|
-
return singleStep.callUrl ? (
|
|
1684
|
+
return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
|
|
1480
1685
|
// if the step is a third party call, we call the third party
|
|
1481
1686
|
// url (singleStep.callUrl) and pass information about the workflow
|
|
1482
1687
|
// in the headers (handled in getHeaders). QStash makes the request
|
|
@@ -1776,9 +1981,10 @@ var wrapTools = ({
|
|
|
1776
1981
|
return Object.fromEntries(
|
|
1777
1982
|
Object.entries(tools).map((toolInfo) => {
|
|
1778
1983
|
const [toolName, tool3] = toolInfo;
|
|
1984
|
+
const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
|
|
1779
1985
|
const aiSDKTool = convertToAISDKTool(tool3);
|
|
1780
1986
|
const execute = aiSDKTool.execute;
|
|
1781
|
-
if (execute) {
|
|
1987
|
+
if (execute && executeAsStep) {
|
|
1782
1988
|
const wrappedExecute = (...params) => {
|
|
1783
1989
|
return context.run(`Run tool ${toolName}`, () => execute(...params));
|
|
1784
1990
|
};
|
|
@@ -2132,6 +2338,11 @@ var WorkflowContext = class {
|
|
|
2132
2338
|
* Number of retries
|
|
2133
2339
|
*/
|
|
2134
2340
|
retries;
|
|
2341
|
+
/**
|
|
2342
|
+
* Settings for controlling the number of active requests
|
|
2343
|
+
* and number of requests per second with the same key.
|
|
2344
|
+
*/
|
|
2345
|
+
flowControl;
|
|
2135
2346
|
constructor({
|
|
2136
2347
|
qstashClient,
|
|
2137
2348
|
workflowRunId,
|
|
@@ -2143,7 +2354,9 @@ var WorkflowContext = class {
|
|
|
2143
2354
|
initialPayload,
|
|
2144
2355
|
env,
|
|
2145
2356
|
retries,
|
|
2146
|
-
telemetry: telemetry2
|
|
2357
|
+
telemetry: telemetry2,
|
|
2358
|
+
invokeCount,
|
|
2359
|
+
flowControl
|
|
2147
2360
|
}) {
|
|
2148
2361
|
this.qstashClient = qstashClient;
|
|
2149
2362
|
this.workflowRunId = workflowRunId;
|
|
@@ -2154,7 +2367,8 @@ var WorkflowContext = class {
|
|
|
2154
2367
|
this.requestPayload = initialPayload;
|
|
2155
2368
|
this.env = env ?? {};
|
|
2156
2369
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2157
|
-
this.
|
|
2370
|
+
this.flowControl = flowControl;
|
|
2371
|
+
this.executor = new AutoExecutor(this, this.steps, telemetry2, invokeCount, debug);
|
|
2158
2372
|
}
|
|
2159
2373
|
/**
|
|
2160
2374
|
* Executes a workflow step
|
|
@@ -2256,7 +2470,7 @@ var WorkflowContext = class {
|
|
|
2256
2470
|
* }
|
|
2257
2471
|
*/
|
|
2258
2472
|
async call(stepName, settings) {
|
|
2259
|
-
const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
|
|
2473
|
+
const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
|
|
2260
2474
|
const result = await this.addStep(
|
|
2261
2475
|
new LazyCallStep(
|
|
2262
2476
|
stepName,
|
|
@@ -2265,7 +2479,8 @@ var WorkflowContext = class {
|
|
|
2265
2479
|
body,
|
|
2266
2480
|
headers,
|
|
2267
2481
|
retries,
|
|
2268
|
-
timeout
|
|
2482
|
+
timeout,
|
|
2483
|
+
flowControl
|
|
2269
2484
|
)
|
|
2270
2485
|
);
|
|
2271
2486
|
if (typeof result === "string") {
|
|
@@ -2502,7 +2717,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2502
2717
|
failureUrl: context.failureUrl,
|
|
2503
2718
|
initialPayload: context.requestPayload,
|
|
2504
2719
|
env: context.env,
|
|
2505
|
-
retries: context.retries
|
|
2720
|
+
retries: context.retries,
|
|
2721
|
+
flowControl: context.flowControl
|
|
2506
2722
|
});
|
|
2507
2723
|
try {
|
|
2508
2724
|
await routeFunction(disabledContext);
|
|
@@ -2655,7 +2871,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2655
2871
|
};
|
|
2656
2872
|
}
|
|
2657
2873
|
};
|
|
2658
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
|
|
2874
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
2659
2875
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
2660
2876
|
return ok("not-failure-callback");
|
|
2661
2877
|
}
|
|
@@ -2667,22 +2883,21 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
2667
2883
|
);
|
|
2668
2884
|
}
|
|
2669
2885
|
try {
|
|
2670
|
-
const { status, header, body, url,
|
|
2671
|
-
requestPayload
|
|
2672
|
-
);
|
|
2886
|
+
const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
|
|
2673
2887
|
const decodedBody = body ? decodeBase64(body) : "{}";
|
|
2674
2888
|
const errorPayload = JSON.parse(decodedBody);
|
|
2675
2889
|
const workflowContext = new WorkflowContext({
|
|
2676
2890
|
qstashClient,
|
|
2677
2891
|
workflowRunId,
|
|
2678
2892
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
2679
|
-
headers: recreateUserHeaders(
|
|
2893
|
+
headers: recreateUserHeaders(request.headers),
|
|
2680
2894
|
steps: [],
|
|
2681
2895
|
url,
|
|
2682
2896
|
failureUrl: url,
|
|
2683
2897
|
debug,
|
|
2684
2898
|
env,
|
|
2685
2899
|
retries,
|
|
2900
|
+
flowControl,
|
|
2686
2901
|
telemetry: void 0
|
|
2687
2902
|
// not going to make requests in authentication check
|
|
2688
2903
|
});
|
|
@@ -2809,7 +3024,8 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2809
3024
|
env,
|
|
2810
3025
|
retries,
|
|
2811
3026
|
useJSONContent,
|
|
2812
|
-
disableTelemetry
|
|
3027
|
+
disableTelemetry,
|
|
3028
|
+
flowControl
|
|
2813
3029
|
} = processOptions(options);
|
|
2814
3030
|
telemetry2 = disableTelemetry ? void 0 : telemetry2;
|
|
2815
3031
|
const debug = WorkflowLogger.getLogger(verbose);
|
|
@@ -2850,6 +3066,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2850
3066
|
failureFunction,
|
|
2851
3067
|
env,
|
|
2852
3068
|
retries,
|
|
3069
|
+
flowControl,
|
|
2853
3070
|
debug
|
|
2854
3071
|
);
|
|
2855
3072
|
if (failureCheck.isErr()) {
|
|
@@ -2858,6 +3075,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2858
3075
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
2859
3076
|
return onStepFinish(workflowRunId, "failure-callback");
|
|
2860
3077
|
}
|
|
3078
|
+
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
2861
3079
|
const workflowContext = new WorkflowContext({
|
|
2862
3080
|
qstashClient,
|
|
2863
3081
|
workflowRunId,
|
|
@@ -2869,7 +3087,9 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2869
3087
|
debug,
|
|
2870
3088
|
env,
|
|
2871
3089
|
retries,
|
|
2872
|
-
telemetry: telemetry2
|
|
3090
|
+
telemetry: telemetry2,
|
|
3091
|
+
invokeCount,
|
|
3092
|
+
flowControl
|
|
2873
3093
|
});
|
|
2874
3094
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
2875
3095
|
routeFunction,
|
|
@@ -2892,6 +3112,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2892
3112
|
workflowUrl,
|
|
2893
3113
|
failureUrl: workflowFailureUrl,
|
|
2894
3114
|
retries,
|
|
3115
|
+
flowControl,
|
|
2895
3116
|
telemetry: telemetry2,
|
|
2896
3117
|
debug
|
|
2897
3118
|
});
|
|
@@ -2901,7 +3122,13 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2901
3122
|
});
|
|
2902
3123
|
throw callReturnCheck.error;
|
|
2903
3124
|
} else if (callReturnCheck.value === "continue-workflow") {
|
|
2904
|
-
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3125
|
+
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3126
|
+
workflowContext,
|
|
3127
|
+
useJSONContent,
|
|
3128
|
+
telemetry: telemetry2,
|
|
3129
|
+
debug,
|
|
3130
|
+
invokeCount
|
|
3131
|
+
}) : await triggerRouteFunction({
|
|
2905
3132
|
onStep: async () => routeFunction(workflowContext),
|
|
2906
3133
|
onCleanup: async (result2) => {
|
|
2907
3134
|
await triggerWorkflowDelete(workflowContext, result2, debug);
|
|
@@ -2936,91 +3163,6 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
2936
3163
|
return { handler: safeHandler };
|
|
2937
3164
|
};
|
|
2938
3165
|
|
|
2939
|
-
// src/serve/serve-many.ts
|
|
2940
|
-
var serveManyBase = ({
|
|
2941
|
-
workflows,
|
|
2942
|
-
getWorkflowId
|
|
2943
|
-
}) => {
|
|
2944
|
-
const workflowIds = [];
|
|
2945
|
-
const workflowMap = Object.fromEntries(
|
|
2946
|
-
Object.entries(workflows).map((workflow) => {
|
|
2947
|
-
const workflowId = workflow[0];
|
|
2948
|
-
if (workflowIds.includes(workflowId)) {
|
|
2949
|
-
throw new WorkflowError(
|
|
2950
|
-
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
2951
|
-
);
|
|
2952
|
-
}
|
|
2953
|
-
if (workflowId.includes("/")) {
|
|
2954
|
-
throw new WorkflowError(
|
|
2955
|
-
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
2956
|
-
);
|
|
2957
|
-
}
|
|
2958
|
-
workflowIds.push(workflowId);
|
|
2959
|
-
workflow[1].workflowId = workflowId;
|
|
2960
|
-
return [workflowId, workflow[1].handler];
|
|
2961
|
-
})
|
|
2962
|
-
);
|
|
2963
|
-
return {
|
|
2964
|
-
handler: async (...params) => {
|
|
2965
|
-
const pickedWorkflowId = getWorkflowId(...params);
|
|
2966
|
-
if (!pickedWorkflowId) {
|
|
2967
|
-
throw new WorkflowError(`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`);
|
|
2968
|
-
}
|
|
2969
|
-
const workflow = workflowMap[pickedWorkflowId];
|
|
2970
|
-
if (!workflow) {
|
|
2971
|
-
throw new WorkflowError(`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`);
|
|
2972
|
-
}
|
|
2973
|
-
return await workflow(...params);
|
|
2974
|
-
}
|
|
2975
|
-
};
|
|
2976
|
-
};
|
|
2977
|
-
var createInvokeCallback = (telemetry2) => {
|
|
2978
|
-
const invokeCallback = async (settings, invokeStep, context) => {
|
|
2979
|
-
const { body, workflow, headers = {}, workflowRunId = getWorkflowRunId(), retries } = settings;
|
|
2980
|
-
const { workflowId } = workflow;
|
|
2981
|
-
if (!workflowId) {
|
|
2982
|
-
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
2983
|
-
}
|
|
2984
|
-
const { headers: invokerHeaders } = getHeaders({
|
|
2985
|
-
initHeaderValue: "false",
|
|
2986
|
-
workflowRunId: context.workflowRunId,
|
|
2987
|
-
workflowUrl: context.url,
|
|
2988
|
-
userHeaders: context.headers,
|
|
2989
|
-
failureUrl: context.failureUrl,
|
|
2990
|
-
retries: context.retries,
|
|
2991
|
-
telemetry: telemetry2
|
|
2992
|
-
});
|
|
2993
|
-
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
2994
|
-
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
2995
|
-
const { headers: triggerHeaders } = getHeaders({
|
|
2996
|
-
initHeaderValue: "true",
|
|
2997
|
-
workflowRunId,
|
|
2998
|
-
workflowUrl: newUrl,
|
|
2999
|
-
userHeaders: new Headers(headers),
|
|
3000
|
-
retries,
|
|
3001
|
-
telemetry: telemetry2
|
|
3002
|
-
});
|
|
3003
|
-
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
3004
|
-
const request = {
|
|
3005
|
-
body: JSON.stringify(body),
|
|
3006
|
-
headers: Object.fromEntries(
|
|
3007
|
-
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
3008
|
-
),
|
|
3009
|
-
workflowRunId,
|
|
3010
|
-
workflowUrl: context.url,
|
|
3011
|
-
step: invokeStep
|
|
3012
|
-
};
|
|
3013
|
-
await context.qstashClient.publish({
|
|
3014
|
-
headers: triggerHeaders,
|
|
3015
|
-
method: "POST",
|
|
3016
|
-
body: JSON.stringify(request),
|
|
3017
|
-
url: newUrl
|
|
3018
|
-
});
|
|
3019
|
-
return void 0;
|
|
3020
|
-
};
|
|
3021
|
-
return invokeCallback;
|
|
3022
|
-
};
|
|
3023
|
-
|
|
3024
3166
|
// platforms/astro.ts
|
|
3025
3167
|
var telemetry = {
|
|
3026
3168
|
sdk: SDK_TELEMETRY,
|
|
@@ -3039,21 +3181,26 @@ function serve(routeFunction, options) {
|
|
|
3039
3181
|
return { POST };
|
|
3040
3182
|
}
|
|
3041
3183
|
var createWorkflow = (...params) => {
|
|
3042
|
-
const
|
|
3184
|
+
const [routeFunction, options = {}] = params;
|
|
3043
3185
|
return {
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3186
|
+
workflowId: void 0,
|
|
3187
|
+
// @ts-expect-error because astro route function has another parameeter,
|
|
3188
|
+
// the RouteFunction type can't cover this. We need to make RouteFunction
|
|
3189
|
+
// accept more variables than simply the context. Until then, ignoring the
|
|
3190
|
+
// error here. Tested the usage in astro project and it's fine. TODO.
|
|
3191
|
+
routeFunction,
|
|
3192
|
+
options
|
|
3047
3193
|
};
|
|
3048
3194
|
};
|
|
3049
|
-
var serveMany = (workflows) => {
|
|
3195
|
+
var serveMany = (workflows, options) => {
|
|
3050
3196
|
return {
|
|
3051
3197
|
POST: serveManyBase({
|
|
3052
3198
|
workflows,
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3199
|
+
getUrl(...params) {
|
|
3200
|
+
return params[0].request.url;
|
|
3201
|
+
},
|
|
3202
|
+
serveMethod: (...params) => serve(...params).POST,
|
|
3203
|
+
options
|
|
3057
3204
|
}).handler
|
|
3058
3205
|
};
|
|
3059
3206
|
};
|