@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
package/solidjs.js
CHANGED
|
@@ -83,12 +83,13 @@ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
|
|
|
83
83
|
var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
84
84
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
85
85
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
86
|
+
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
86
87
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
87
88
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
88
89
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
89
90
|
var NO_CONCURRENCY = 1;
|
|
90
91
|
var DEFAULT_RETRIES = 3;
|
|
91
|
-
var VERSION = "v0.2.
|
|
92
|
+
var VERSION = "v0.2.7";
|
|
92
93
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
93
94
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
94
95
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -135,6 +136,31 @@ var formatWorkflowError = (error) => {
|
|
|
135
136
|
};
|
|
136
137
|
};
|
|
137
138
|
|
|
139
|
+
// src/utils.ts
|
|
140
|
+
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
141
|
+
var NANOID_LENGTH = 21;
|
|
142
|
+
function getRandomInt() {
|
|
143
|
+
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
144
|
+
}
|
|
145
|
+
function nanoid() {
|
|
146
|
+
return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
|
|
147
|
+
}
|
|
148
|
+
function getWorkflowRunId(id) {
|
|
149
|
+
return `wfr_${id ?? nanoid()}`;
|
|
150
|
+
}
|
|
151
|
+
function decodeBase64(base64) {
|
|
152
|
+
try {
|
|
153
|
+
const binString = atob(base64);
|
|
154
|
+
const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
155
|
+
return new TextDecoder().decode(intArray);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.warn(
|
|
158
|
+
`Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
|
|
159
|
+
);
|
|
160
|
+
return atob(base64);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
138
164
|
// src/context/steps.ts
|
|
139
165
|
var BaseLazyStep = class {
|
|
140
166
|
stepName;
|
|
@@ -239,8 +265,9 @@ var LazyCallStep = class extends BaseLazyStep {
|
|
|
239
265
|
headers;
|
|
240
266
|
retries;
|
|
241
267
|
timeout;
|
|
268
|
+
flowControl;
|
|
242
269
|
stepType = "Call";
|
|
243
|
-
constructor(stepName, url, method, body, headers, retries, timeout) {
|
|
270
|
+
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
244
271
|
super(stepName);
|
|
245
272
|
this.url = url;
|
|
246
273
|
this.method = method;
|
|
@@ -248,6 +275,7 @@ var LazyCallStep = class extends BaseLazyStep {
|
|
|
248
275
|
this.headers = headers;
|
|
249
276
|
this.retries = retries;
|
|
250
277
|
this.timeout = timeout;
|
|
278
|
+
this.flowControl = flowControl;
|
|
251
279
|
}
|
|
252
280
|
getPlanStep(concurrent, targetStep) {
|
|
253
281
|
return {
|
|
@@ -315,6 +343,49 @@ var LazyNotifyStep = class extends LazyFunctionStep {
|
|
|
315
343
|
});
|
|
316
344
|
}
|
|
317
345
|
};
|
|
346
|
+
var LazyInvokeStep = class extends BaseLazyStep {
|
|
347
|
+
stepType = "Invoke";
|
|
348
|
+
params;
|
|
349
|
+
constructor(stepName, {
|
|
350
|
+
workflow,
|
|
351
|
+
body,
|
|
352
|
+
headers = {},
|
|
353
|
+
workflowRunId,
|
|
354
|
+
retries,
|
|
355
|
+
flowControl
|
|
356
|
+
}) {
|
|
357
|
+
super(stepName);
|
|
358
|
+
this.params = {
|
|
359
|
+
workflow,
|
|
360
|
+
body,
|
|
361
|
+
headers,
|
|
362
|
+
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
363
|
+
retries,
|
|
364
|
+
flowControl
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
getPlanStep(concurrent, targetStep) {
|
|
368
|
+
return {
|
|
369
|
+
stepId: 0,
|
|
370
|
+
stepName: this.stepName,
|
|
371
|
+
stepType: this.stepType,
|
|
372
|
+
concurrent,
|
|
373
|
+
targetStep
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* won't be used as it's the server who will add the result step
|
|
378
|
+
* in Invoke step.
|
|
379
|
+
*/
|
|
380
|
+
getResultStep(concurrent, stepId) {
|
|
381
|
+
return Promise.resolve({
|
|
382
|
+
stepId,
|
|
383
|
+
stepName: this.stepName,
|
|
384
|
+
stepType: this.stepType,
|
|
385
|
+
concurrent
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
};
|
|
318
389
|
|
|
319
390
|
// node_modules/neverthrow/dist/index.es.js
|
|
320
391
|
var defaultErrorConfig = {
|
|
@@ -739,7 +810,8 @@ var StepTypes = [
|
|
|
739
810
|
"SleepUntil",
|
|
740
811
|
"Call",
|
|
741
812
|
"Wait",
|
|
742
|
-
"Notify"
|
|
813
|
+
"Notify",
|
|
814
|
+
"Invoke"
|
|
743
815
|
];
|
|
744
816
|
|
|
745
817
|
// src/workflow-requests.ts
|
|
@@ -748,7 +820,8 @@ var triggerFirstInvocation = async ({
|
|
|
748
820
|
workflowContext,
|
|
749
821
|
useJSONContent,
|
|
750
822
|
telemetry,
|
|
751
|
-
debug
|
|
823
|
+
debug,
|
|
824
|
+
invokeCount
|
|
752
825
|
}) => {
|
|
753
826
|
const { headers } = getHeaders({
|
|
754
827
|
initHeaderValue: "true",
|
|
@@ -757,7 +830,9 @@ var triggerFirstInvocation = async ({
|
|
|
757
830
|
userHeaders: workflowContext.headers,
|
|
758
831
|
failureUrl: workflowContext.failureUrl,
|
|
759
832
|
retries: workflowContext.retries,
|
|
760
|
-
telemetry
|
|
833
|
+
telemetry,
|
|
834
|
+
invokeCount,
|
|
835
|
+
flowControl: workflowContext.flowControl
|
|
761
836
|
});
|
|
762
837
|
if (workflowContext.headers.get("content-type")) {
|
|
763
838
|
headers["content-type"] = workflowContext.headers.get("content-type");
|
|
@@ -803,8 +878,8 @@ var triggerRouteFunction = async ({
|
|
|
803
878
|
debug
|
|
804
879
|
}) => {
|
|
805
880
|
try {
|
|
806
|
-
await onStep();
|
|
807
|
-
await onCleanup();
|
|
881
|
+
const result = await onStep();
|
|
882
|
+
await onCleanup(result);
|
|
808
883
|
return ok("workflow-finished");
|
|
809
884
|
} catch (error) {
|
|
810
885
|
const error_ = error;
|
|
@@ -825,14 +900,15 @@ var triggerRouteFunction = async ({
|
|
|
825
900
|
}
|
|
826
901
|
}
|
|
827
902
|
};
|
|
828
|
-
var triggerWorkflowDelete = async (workflowContext, debug, cancel = false) => {
|
|
903
|
+
var triggerWorkflowDelete = async (workflowContext, result, debug, cancel = false) => {
|
|
829
904
|
await debug?.log("SUBMIT", "SUBMIT_CLEANUP", {
|
|
830
905
|
deletedWorkflowRunId: workflowContext.workflowRunId
|
|
831
906
|
});
|
|
832
907
|
await workflowContext.qstashClient.http.request({
|
|
833
908
|
path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
|
|
834
909
|
method: "DELETE",
|
|
835
|
-
parseResponseAsJson: false
|
|
910
|
+
parseResponseAsJson: false,
|
|
911
|
+
body: JSON.stringify(result)
|
|
836
912
|
});
|
|
837
913
|
await debug?.log(
|
|
838
914
|
"SUBMIT",
|
|
@@ -862,6 +938,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
862
938
|
failureUrl,
|
|
863
939
|
retries,
|
|
864
940
|
telemetry,
|
|
941
|
+
flowControl,
|
|
865
942
|
debug
|
|
866
943
|
}) => {
|
|
867
944
|
try {
|
|
@@ -909,6 +986,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
909
986
|
const stepType = request.headers.get("Upstash-Workflow-StepType");
|
|
910
987
|
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
911
988
|
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
989
|
+
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
912
990
|
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
913
991
|
throw new Error(
|
|
914
992
|
`Missing info in callback message source header: ${JSON.stringify({
|
|
@@ -929,7 +1007,9 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
929
1007
|
userHeaders,
|
|
930
1008
|
failureUrl,
|
|
931
1009
|
retries,
|
|
932
|
-
telemetry
|
|
1010
|
+
telemetry,
|
|
1011
|
+
invokeCount: Number(invokeCount),
|
|
1012
|
+
flowControl
|
|
933
1013
|
});
|
|
934
1014
|
const callResponse = {
|
|
935
1015
|
status: callbackMessage.status,
|
|
@@ -985,15 +1065,24 @@ var getHeaders = ({
|
|
|
985
1065
|
step,
|
|
986
1066
|
callRetries,
|
|
987
1067
|
callTimeout,
|
|
988
|
-
telemetry
|
|
1068
|
+
telemetry,
|
|
1069
|
+
invokeCount,
|
|
1070
|
+
flowControl,
|
|
1071
|
+
callFlowControl
|
|
989
1072
|
}) => {
|
|
1073
|
+
const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
990
1074
|
const baseHeaders = {
|
|
991
1075
|
[WORKFLOW_INIT_HEADER]: initHeaderValue,
|
|
992
1076
|
[WORKFLOW_ID_HEADER]: workflowRunId,
|
|
993
1077
|
[WORKFLOW_URL_HEADER]: workflowUrl,
|
|
994
1078
|
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1079
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1080
|
+
"content-type": contentType,
|
|
995
1081
|
...telemetry ? getTelemetryHeaders(telemetry) : {}
|
|
996
1082
|
};
|
|
1083
|
+
if (invokeCount !== void 0 && !step?.callUrl) {
|
|
1084
|
+
baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
|
|
1085
|
+
}
|
|
997
1086
|
if (!step?.callUrl) {
|
|
998
1087
|
baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
999
1088
|
}
|
|
@@ -1010,6 +1099,11 @@ var getHeaders = ({
|
|
|
1010
1099
|
if (retries !== void 0) {
|
|
1011
1100
|
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1012
1101
|
}
|
|
1102
|
+
if (flowControl) {
|
|
1103
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1104
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
|
|
1105
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
|
|
1106
|
+
}
|
|
1013
1107
|
if (!step?.callUrl) {
|
|
1014
1108
|
baseHeaders["Upstash-Failure-Callback"] = failureUrl;
|
|
1015
1109
|
}
|
|
@@ -1021,9 +1115,26 @@ var getHeaders = ({
|
|
|
1021
1115
|
baseHeaders["Upstash-Callback-Retries"] = retries.toString();
|
|
1022
1116
|
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1023
1117
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1118
|
+
if (callFlowControl) {
|
|
1119
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
|
|
1120
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1121
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1122
|
+
}
|
|
1123
|
+
if (flowControl) {
|
|
1124
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1125
|
+
baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
|
|
1126
|
+
baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
if (flowControl) {
|
|
1130
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1131
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1132
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1133
|
+
}
|
|
1134
|
+
if (retries !== void 0) {
|
|
1135
|
+
baseHeaders["Upstash-Retries"] = retries.toString();
|
|
1136
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1137
|
+
}
|
|
1027
1138
|
}
|
|
1028
1139
|
if (userHeaders) {
|
|
1029
1140
|
for (const header of userHeaders.keys()) {
|
|
@@ -1035,7 +1146,6 @@ var getHeaders = ({
|
|
|
1035
1146
|
baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
|
|
1036
1147
|
}
|
|
1037
1148
|
}
|
|
1038
|
-
const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
1039
1149
|
if (step?.callHeaders) {
|
|
1040
1150
|
const forwardedHeaders = Object.fromEntries(
|
|
1041
1151
|
Object.entries(step.callHeaders).map(([header, value]) => [
|
|
@@ -1059,6 +1169,7 @@ var getHeaders = ({
|
|
|
1059
1169
|
"Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
|
|
1060
1170
|
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
1061
1171
|
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
1172
|
+
[`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
|
|
1062
1173
|
"Upstash-Workflow-CallType": "toCallback"
|
|
1063
1174
|
}
|
|
1064
1175
|
};
|
|
@@ -1085,8 +1196,7 @@ var getHeaders = ({
|
|
|
1085
1196
|
"Upstash-Workflow-Runid": [workflowRunId],
|
|
1086
1197
|
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
1087
1198
|
[WORKFLOW_URL_HEADER]: [workflowUrl],
|
|
1088
|
-
"Upstash-Workflow-CallType": ["step"]
|
|
1089
|
-
"Content-Type": [contentType]
|
|
1199
|
+
"Upstash-Workflow-CallType": ["step"]
|
|
1090
1200
|
}
|
|
1091
1201
|
};
|
|
1092
1202
|
}
|
|
@@ -1117,9 +1227,98 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
|
|
|
1117
1227
|
);
|
|
1118
1228
|
}
|
|
1119
1229
|
};
|
|
1230
|
+
var prepareFlowControl = (flowControl) => {
|
|
1231
|
+
const parallelism = flowControl.parallelism?.toString();
|
|
1232
|
+
const rate = flowControl.ratePerSecond?.toString();
|
|
1233
|
+
const controlValue = [
|
|
1234
|
+
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
1235
|
+
rate ? `rate=${rate}` : void 0
|
|
1236
|
+
].filter(Boolean);
|
|
1237
|
+
if (controlValue.length === 0) {
|
|
1238
|
+
throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
1239
|
+
}
|
|
1240
|
+
return {
|
|
1241
|
+
flowControlKey: flowControl.key,
|
|
1242
|
+
flowControlValue: controlValue.join(", ")
|
|
1243
|
+
};
|
|
1244
|
+
};
|
|
1120
1245
|
|
|
1121
1246
|
// src/context/auto-executor.ts
|
|
1122
1247
|
var import_qstash4 = require("@upstash/qstash");
|
|
1248
|
+
|
|
1249
|
+
// src/serve/serve-many.ts
|
|
1250
|
+
var invokeWorkflow = async ({
|
|
1251
|
+
settings,
|
|
1252
|
+
invokeStep,
|
|
1253
|
+
context,
|
|
1254
|
+
invokeCount,
|
|
1255
|
+
telemetry
|
|
1256
|
+
}) => {
|
|
1257
|
+
const {
|
|
1258
|
+
body,
|
|
1259
|
+
workflow,
|
|
1260
|
+
headers = {},
|
|
1261
|
+
workflowRunId = getWorkflowRunId(),
|
|
1262
|
+
retries,
|
|
1263
|
+
flowControl
|
|
1264
|
+
} = settings;
|
|
1265
|
+
const { workflowId } = workflow;
|
|
1266
|
+
const {
|
|
1267
|
+
retries: workflowRetries,
|
|
1268
|
+
failureFunction,
|
|
1269
|
+
failureUrl,
|
|
1270
|
+
useJSONContent,
|
|
1271
|
+
flowControl: workflowFlowControl
|
|
1272
|
+
} = workflow.options;
|
|
1273
|
+
if (!workflowId) {
|
|
1274
|
+
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
1275
|
+
}
|
|
1276
|
+
const { headers: invokerHeaders } = getHeaders({
|
|
1277
|
+
initHeaderValue: "false",
|
|
1278
|
+
workflowRunId: context.workflowRunId,
|
|
1279
|
+
workflowUrl: context.url,
|
|
1280
|
+
userHeaders: context.headers,
|
|
1281
|
+
failureUrl: context.failureUrl,
|
|
1282
|
+
retries: context.retries,
|
|
1283
|
+
telemetry,
|
|
1284
|
+
invokeCount,
|
|
1285
|
+
flowControl: context.flowControl
|
|
1286
|
+
});
|
|
1287
|
+
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1288
|
+
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
1289
|
+
const { headers: triggerHeaders } = getHeaders({
|
|
1290
|
+
initHeaderValue: "true",
|
|
1291
|
+
workflowRunId,
|
|
1292
|
+
workflowUrl: newUrl,
|
|
1293
|
+
userHeaders: new Headers(headers),
|
|
1294
|
+
retries: retries ?? workflowRetries,
|
|
1295
|
+
telemetry,
|
|
1296
|
+
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1297
|
+
invokeCount: invokeCount + 1,
|
|
1298
|
+
flowControl: flowControl ?? workflowFlowControl
|
|
1299
|
+
});
|
|
1300
|
+
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1301
|
+
if (useJSONContent) {
|
|
1302
|
+
triggerHeaders["content-type"] = "application/json";
|
|
1303
|
+
}
|
|
1304
|
+
const request = {
|
|
1305
|
+
body: JSON.stringify(body),
|
|
1306
|
+
headers: Object.fromEntries(
|
|
1307
|
+
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1308
|
+
),
|
|
1309
|
+
workflowRunId,
|
|
1310
|
+
workflowUrl: context.url,
|
|
1311
|
+
step: invokeStep
|
|
1312
|
+
};
|
|
1313
|
+
await context.qstashClient.publish({
|
|
1314
|
+
headers: triggerHeaders,
|
|
1315
|
+
method: "POST",
|
|
1316
|
+
body: JSON.stringify(request),
|
|
1317
|
+
url: newUrl
|
|
1318
|
+
});
|
|
1319
|
+
};
|
|
1320
|
+
|
|
1321
|
+
// src/context/auto-executor.ts
|
|
1123
1322
|
var AutoExecutor = class _AutoExecutor {
|
|
1124
1323
|
context;
|
|
1125
1324
|
promises = /* @__PURE__ */ new WeakMap();
|
|
@@ -1128,14 +1327,16 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1128
1327
|
nonPlanStepCount;
|
|
1129
1328
|
steps;
|
|
1130
1329
|
indexInCurrentList = 0;
|
|
1330
|
+
invokeCount;
|
|
1131
1331
|
telemetry;
|
|
1132
1332
|
stepCount = 0;
|
|
1133
1333
|
planStepCount = 0;
|
|
1134
1334
|
executingStep = false;
|
|
1135
|
-
constructor(context, steps, telemetry, debug) {
|
|
1335
|
+
constructor(context, steps, telemetry, invokeCount, debug) {
|
|
1136
1336
|
this.context = context;
|
|
1137
1337
|
this.steps = steps;
|
|
1138
1338
|
this.telemetry = telemetry;
|
|
1339
|
+
this.invokeCount = invokeCount ?? 0;
|
|
1139
1340
|
this.debug = debug;
|
|
1140
1341
|
this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
|
|
1141
1342
|
}
|
|
@@ -1358,7 +1559,9 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1358
1559
|
step: waitStep,
|
|
1359
1560
|
failureUrl: this.context.failureUrl,
|
|
1360
1561
|
retries: this.context.retries,
|
|
1361
|
-
telemetry: this.telemetry
|
|
1562
|
+
telemetry: this.telemetry,
|
|
1563
|
+
invokeCount: this.invokeCount,
|
|
1564
|
+
flowControl: this.context.flowControl
|
|
1362
1565
|
});
|
|
1363
1566
|
const waitBody = {
|
|
1364
1567
|
url: this.context.url,
|
|
@@ -1381,7 +1584,19 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1381
1584
|
method: "POST",
|
|
1382
1585
|
parseResponseAsJson: false
|
|
1383
1586
|
});
|
|
1384
|
-
throw new WorkflowAbort(
|
|
1587
|
+
throw new WorkflowAbort(waitStep.stepName, waitStep);
|
|
1588
|
+
}
|
|
1589
|
+
if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
|
|
1590
|
+
const invokeStep = steps[0];
|
|
1591
|
+
const lazyInvokeStep = lazySteps[0];
|
|
1592
|
+
await invokeWorkflow({
|
|
1593
|
+
settings: lazyInvokeStep.params,
|
|
1594
|
+
invokeStep,
|
|
1595
|
+
context: this.context,
|
|
1596
|
+
invokeCount: this.invokeCount,
|
|
1597
|
+
telemetry: this.telemetry
|
|
1598
|
+
});
|
|
1599
|
+
throw new WorkflowAbort(invokeStep.stepName, invokeStep);
|
|
1385
1600
|
}
|
|
1386
1601
|
const result = await this.context.qstashClient.batchJSON(
|
|
1387
1602
|
steps.map((singleStep, index) => {
|
|
@@ -1396,11 +1611,14 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1396
1611
|
retries: this.context.retries,
|
|
1397
1612
|
callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
|
|
1398
1613
|
callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
|
|
1399
|
-
telemetry: this.telemetry
|
|
1614
|
+
telemetry: this.telemetry,
|
|
1615
|
+
invokeCount: this.invokeCount,
|
|
1616
|
+
flowControl: this.context.flowControl,
|
|
1617
|
+
callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
|
|
1400
1618
|
});
|
|
1401
1619
|
const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
|
|
1402
1620
|
singleStep.out = JSON.stringify(singleStep.out);
|
|
1403
|
-
return singleStep.callUrl ? (
|
|
1621
|
+
return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
|
|
1404
1622
|
// if the step is a third party call, we call the third party
|
|
1405
1623
|
// url (singleStep.callUrl) and pass information about the workflow
|
|
1406
1624
|
// in the headers (handled in getHeaders). QStash makes the request
|
|
@@ -2057,6 +2275,11 @@ var WorkflowContext = class {
|
|
|
2057
2275
|
* Number of retries
|
|
2058
2276
|
*/
|
|
2059
2277
|
retries;
|
|
2278
|
+
/**
|
|
2279
|
+
* Settings for controlling the number of active requests
|
|
2280
|
+
* and number of requests per second with the same key.
|
|
2281
|
+
*/
|
|
2282
|
+
flowControl;
|
|
2060
2283
|
constructor({
|
|
2061
2284
|
qstashClient,
|
|
2062
2285
|
workflowRunId,
|
|
@@ -2068,7 +2291,9 @@ var WorkflowContext = class {
|
|
|
2068
2291
|
initialPayload,
|
|
2069
2292
|
env,
|
|
2070
2293
|
retries,
|
|
2071
|
-
telemetry
|
|
2294
|
+
telemetry,
|
|
2295
|
+
invokeCount,
|
|
2296
|
+
flowControl
|
|
2072
2297
|
}) {
|
|
2073
2298
|
this.qstashClient = qstashClient;
|
|
2074
2299
|
this.workflowRunId = workflowRunId;
|
|
@@ -2079,7 +2304,8 @@ var WorkflowContext = class {
|
|
|
2079
2304
|
this.requestPayload = initialPayload;
|
|
2080
2305
|
this.env = env ?? {};
|
|
2081
2306
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2082
|
-
this.
|
|
2307
|
+
this.flowControl = flowControl;
|
|
2308
|
+
this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
|
|
2083
2309
|
}
|
|
2084
2310
|
/**
|
|
2085
2311
|
* Executes a workflow step
|
|
@@ -2181,7 +2407,7 @@ var WorkflowContext = class {
|
|
|
2181
2407
|
* }
|
|
2182
2408
|
*/
|
|
2183
2409
|
async call(stepName, settings) {
|
|
2184
|
-
const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
|
|
2410
|
+
const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
|
|
2185
2411
|
const result = await this.addStep(
|
|
2186
2412
|
new LazyCallStep(
|
|
2187
2413
|
stepName,
|
|
@@ -2190,7 +2416,8 @@ var WorkflowContext = class {
|
|
|
2190
2416
|
body,
|
|
2191
2417
|
headers,
|
|
2192
2418
|
retries,
|
|
2193
|
-
timeout
|
|
2419
|
+
timeout,
|
|
2420
|
+
flowControl
|
|
2194
2421
|
)
|
|
2195
2422
|
);
|
|
2196
2423
|
if (typeof result === "string") {
|
|
@@ -2299,6 +2526,13 @@ var WorkflowContext = class {
|
|
|
2299
2526
|
return result;
|
|
2300
2527
|
}
|
|
2301
2528
|
}
|
|
2529
|
+
async invoke(stepName, settings) {
|
|
2530
|
+
const result = await this.addStep(new LazyInvokeStep(stepName, settings));
|
|
2531
|
+
return {
|
|
2532
|
+
...result,
|
|
2533
|
+
body: result.body ? JSON.parse(result.body) : void 0
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2302
2536
|
/**
|
|
2303
2537
|
* Cancel the current workflow run
|
|
2304
2538
|
*
|
|
@@ -2376,31 +2610,6 @@ var WorkflowLogger = class _WorkflowLogger {
|
|
|
2376
2610
|
}
|
|
2377
2611
|
};
|
|
2378
2612
|
|
|
2379
|
-
// src/utils.ts
|
|
2380
|
-
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
2381
|
-
var NANOID_LENGTH = 21;
|
|
2382
|
-
function getRandomInt() {
|
|
2383
|
-
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
2384
|
-
}
|
|
2385
|
-
function nanoid() {
|
|
2386
|
-
return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
|
|
2387
|
-
}
|
|
2388
|
-
function getWorkflowRunId(id) {
|
|
2389
|
-
return `wfr_${id ?? nanoid()}`;
|
|
2390
|
-
}
|
|
2391
|
-
function decodeBase64(base64) {
|
|
2392
|
-
try {
|
|
2393
|
-
const binString = atob(base64);
|
|
2394
|
-
const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
2395
|
-
return new TextDecoder().decode(intArray);
|
|
2396
|
-
} catch (error) {
|
|
2397
|
-
console.warn(
|
|
2398
|
-
`Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
|
|
2399
|
-
);
|
|
2400
|
-
return atob(base64);
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2404
2613
|
// src/serve/authorization.ts
|
|
2405
2614
|
var import_qstash8 = require("@upstash/qstash");
|
|
2406
2615
|
var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
|
|
@@ -2445,7 +2654,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2445
2654
|
failureUrl: context.failureUrl,
|
|
2446
2655
|
initialPayload: context.requestPayload,
|
|
2447
2656
|
env: context.env,
|
|
2448
|
-
retries: context.retries
|
|
2657
|
+
retries: context.retries,
|
|
2658
|
+
flowControl: context.flowControl
|
|
2449
2659
|
});
|
|
2450
2660
|
try {
|
|
2451
2661
|
await routeFunction(disabledContext);
|
|
@@ -2598,7 +2808,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2598
2808
|
};
|
|
2599
2809
|
}
|
|
2600
2810
|
};
|
|
2601
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
|
|
2811
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
2602
2812
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
2603
2813
|
return ok("not-failure-callback");
|
|
2604
2814
|
}
|
|
@@ -2610,22 +2820,21 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
2610
2820
|
);
|
|
2611
2821
|
}
|
|
2612
2822
|
try {
|
|
2613
|
-
const { status, header, body, url,
|
|
2614
|
-
requestPayload
|
|
2615
|
-
);
|
|
2823
|
+
const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
|
|
2616
2824
|
const decodedBody = body ? decodeBase64(body) : "{}";
|
|
2617
2825
|
const errorPayload = JSON.parse(decodedBody);
|
|
2618
2826
|
const workflowContext = new WorkflowContext({
|
|
2619
2827
|
qstashClient,
|
|
2620
2828
|
workflowRunId,
|
|
2621
2829
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
2622
|
-
headers: recreateUserHeaders(
|
|
2830
|
+
headers: recreateUserHeaders(request.headers),
|
|
2623
2831
|
steps: [],
|
|
2624
2832
|
url,
|
|
2625
2833
|
failureUrl: url,
|
|
2626
2834
|
debug,
|
|
2627
2835
|
env,
|
|
2628
2836
|
retries,
|
|
2837
|
+
flowControl,
|
|
2629
2838
|
telemetry: void 0
|
|
2630
2839
|
// not going to make requests in authentication check
|
|
2631
2840
|
});
|
|
@@ -2752,7 +2961,8 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2752
2961
|
env,
|
|
2753
2962
|
retries,
|
|
2754
2963
|
useJSONContent,
|
|
2755
|
-
disableTelemetry
|
|
2964
|
+
disableTelemetry,
|
|
2965
|
+
flowControl
|
|
2756
2966
|
} = processOptions(options);
|
|
2757
2967
|
telemetry = disableTelemetry ? void 0 : telemetry;
|
|
2758
2968
|
const debug = WorkflowLogger.getLogger(verbose);
|
|
@@ -2793,6 +3003,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2793
3003
|
failureFunction,
|
|
2794
3004
|
env,
|
|
2795
3005
|
retries,
|
|
3006
|
+
flowControl,
|
|
2796
3007
|
debug
|
|
2797
3008
|
);
|
|
2798
3009
|
if (failureCheck.isErr()) {
|
|
@@ -2801,6 +3012,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2801
3012
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
2802
3013
|
return onStepFinish(workflowRunId, "failure-callback");
|
|
2803
3014
|
}
|
|
3015
|
+
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
2804
3016
|
const workflowContext = new WorkflowContext({
|
|
2805
3017
|
qstashClient,
|
|
2806
3018
|
workflowRunId,
|
|
@@ -2812,7 +3024,9 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2812
3024
|
debug,
|
|
2813
3025
|
env,
|
|
2814
3026
|
retries,
|
|
2815
|
-
telemetry
|
|
3027
|
+
telemetry,
|
|
3028
|
+
invokeCount,
|
|
3029
|
+
flowControl
|
|
2816
3030
|
});
|
|
2817
3031
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
2818
3032
|
routeFunction,
|
|
@@ -2835,6 +3049,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2835
3049
|
workflowUrl,
|
|
2836
3050
|
failureUrl: workflowFailureUrl,
|
|
2837
3051
|
retries,
|
|
3052
|
+
flowControl,
|
|
2838
3053
|
telemetry,
|
|
2839
3054
|
debug
|
|
2840
3055
|
});
|
|
@@ -2844,10 +3059,16 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2844
3059
|
});
|
|
2845
3060
|
throw callReturnCheck.error;
|
|
2846
3061
|
} else if (callReturnCheck.value === "continue-workflow") {
|
|
2847
|
-
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3062
|
+
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3063
|
+
workflowContext,
|
|
3064
|
+
useJSONContent,
|
|
3065
|
+
telemetry,
|
|
3066
|
+
debug,
|
|
3067
|
+
invokeCount
|
|
3068
|
+
}) : await triggerRouteFunction({
|
|
2848
3069
|
onStep: async () => routeFunction(workflowContext),
|
|
2849
|
-
onCleanup: async () => {
|
|
2850
|
-
await triggerWorkflowDelete(workflowContext, debug);
|
|
3070
|
+
onCleanup: async (result2) => {
|
|
3071
|
+
await triggerWorkflowDelete(workflowContext, result2, debug);
|
|
2851
3072
|
},
|
|
2852
3073
|
onCancel: async () => {
|
|
2853
3074
|
await makeCancelRequest(workflowContext.qstashClient.http, workflowRunId);
|
|
@@ -2881,6 +3102,11 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
2881
3102
|
|
|
2882
3103
|
// platforms/solidjs.ts
|
|
2883
3104
|
var serve = (routeFunction, options) => {
|
|
3105
|
+
const telemetry = {
|
|
3106
|
+
sdk: SDK_TELEMETRY,
|
|
3107
|
+
framework: "solidjs",
|
|
3108
|
+
runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
|
|
3109
|
+
};
|
|
2884
3110
|
const handler = async (event) => {
|
|
2885
3111
|
const method = event.request.method;
|
|
2886
3112
|
if (method.toUpperCase() !== "POST") {
|
|
@@ -2888,15 +3114,7 @@ var serve = (routeFunction, options) => {
|
|
|
2888
3114
|
status: 405
|
|
2889
3115
|
});
|
|
2890
3116
|
}
|
|
2891
|
-
const { handler: serveHandler } = serveBase(
|
|
2892
|
-
routeFunction,
|
|
2893
|
-
{
|
|
2894
|
-
sdk: SDK_TELEMETRY,
|
|
2895
|
-
framework: "solidjs",
|
|
2896
|
-
runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
|
|
2897
|
-
},
|
|
2898
|
-
options
|
|
2899
|
-
);
|
|
3117
|
+
const { handler: serveHandler } = serveBase(routeFunction, telemetry, options);
|
|
2900
3118
|
return await serveHandler(event.request);
|
|
2901
3119
|
};
|
|
2902
3120
|
return { POST: handler };
|