@upstash/workflow 0.2.16 → 0.2.18
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 +2 -2
- package/astro.d.ts +2 -2
- package/astro.js +201 -41
- package/astro.mjs +1 -1
- package/{chunk-TGEGSOSN.mjs → chunk-EHL7SSJF.mjs} +202 -41
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +201 -41
- package/cloudflare.mjs +1 -1
- package/express.d.mts +2 -2
- package/express.d.ts +2 -2
- package/express.js +7086 -7201
- package/express.mjs +6706 -6981
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +201 -41
- package/h3.mjs +1 -1
- package/hono.d.mts +2 -2
- package/hono.d.ts +2 -2
- package/hono.js +201 -41
- package/hono.mjs +1 -1
- package/index.d.mts +131 -11
- package/index.d.ts +131 -11
- package/index.js +218 -42
- package/index.mjs +27 -4
- package/nextjs.d.mts +2 -2
- package/nextjs.d.ts +2 -2
- package/nextjs.js +204 -41
- package/nextjs.mjs +4 -1
- package/package.json +1 -1
- package/{serve-many-AaKSQyi7.d.ts → serve-many-BObe3pdI.d.ts} +1 -1
- package/{serve-many-AFwJPR3S.d.mts → serve-many-CEUYWQvV.d.mts} +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +193 -39
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +2 -2
- package/svelte.d.ts +2 -2
- package/svelte.js +201 -41
- package/svelte.mjs +1 -1
- package/{types-Dd-3bPoU.d.ts → types-B7_5AkKQ.d.mts} +118 -14
- package/{types-Dd-3bPoU.d.mts → types-B7_5AkKQ.d.ts} +118 -14
package/nextjs.js
CHANGED
|
@@ -89,12 +89,13 @@ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
|
89
89
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
90
90
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
91
91
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
92
|
+
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
92
93
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
93
94
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
94
95
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
95
96
|
var NO_CONCURRENCY = 1;
|
|
96
97
|
var DEFAULT_RETRIES = 3;
|
|
97
|
-
var VERSION = "v0.2.
|
|
98
|
+
var VERSION = "v0.2.18";
|
|
98
99
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
99
100
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
100
101
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -624,6 +625,7 @@ var triggerFirstInvocation = async (params) => {
|
|
|
624
625
|
workflowUrl: workflowContext.url,
|
|
625
626
|
failureUrl: workflowContext.failureUrl,
|
|
626
627
|
retries: workflowContext.retries,
|
|
628
|
+
retryDelay: workflowContext.retryDelay,
|
|
627
629
|
telemetry,
|
|
628
630
|
flowControl: workflowContext.flowControl,
|
|
629
631
|
useJSONContent: useJSONContent ?? false
|
|
@@ -637,6 +639,9 @@ var triggerFirstInvocation = async (params) => {
|
|
|
637
639
|
if (useJSONContent) {
|
|
638
640
|
headers["content-type"] = "application/json";
|
|
639
641
|
}
|
|
642
|
+
if (workflowContext.label) {
|
|
643
|
+
headers[WORKFLOW_LABEL_HEADER] = workflowContext.label;
|
|
644
|
+
}
|
|
640
645
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
641
646
|
return {
|
|
642
647
|
headers,
|
|
@@ -737,10 +742,11 @@ var recreateUserHeaders = (headers) => {
|
|
|
737
742
|
const pairs = headers.entries();
|
|
738
743
|
for (const [header, value] of pairs) {
|
|
739
744
|
const headerLowerCase = header.toLowerCase();
|
|
740
|
-
|
|
745
|
+
const isUserHeader = !headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
741
746
|
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
742
747
|
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
743
|
-
headerLowerCase !== "render-proxy-ttl")
|
|
748
|
+
headerLowerCase !== "render-proxy-ttl" || headerLowerCase === WORKFLOW_LABEL_HEADER.toLocaleLowerCase();
|
|
749
|
+
if (isUserHeader) {
|
|
744
750
|
filteredHeaders.append(header, value);
|
|
745
751
|
}
|
|
746
752
|
}
|
|
@@ -753,6 +759,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
753
759
|
workflowUrl,
|
|
754
760
|
failureUrl,
|
|
755
761
|
retries,
|
|
762
|
+
retryDelay,
|
|
756
763
|
telemetry,
|
|
757
764
|
flowControl,
|
|
758
765
|
debug
|
|
@@ -823,6 +830,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
823
830
|
workflowUrl,
|
|
824
831
|
failureUrl,
|
|
825
832
|
retries,
|
|
833
|
+
retryDelay,
|
|
826
834
|
telemetry,
|
|
827
835
|
flowControl
|
|
828
836
|
},
|
|
@@ -973,7 +981,8 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
973
981
|
workflowRunId: context.workflowRunId,
|
|
974
982
|
workflowUrl: context.url,
|
|
975
983
|
failureUrl: context.failureUrl,
|
|
976
|
-
retries: context.retries,
|
|
984
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
985
|
+
retryDelay: context.retryDelay,
|
|
977
986
|
useJSONContent: false,
|
|
978
987
|
telemetry,
|
|
979
988
|
flowControl: context.flowControl
|
|
@@ -992,6 +1001,9 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
992
1001
|
body,
|
|
993
1002
|
headers,
|
|
994
1003
|
method: "POST",
|
|
1004
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1005
|
+
retryDelay: context.retryDelay,
|
|
1006
|
+
flowControl: context.flowControl,
|
|
995
1007
|
url: context.url
|
|
996
1008
|
}
|
|
997
1009
|
]);
|
|
@@ -1062,6 +1074,9 @@ var LazySleepStep = class extends BaseLazyStep {
|
|
|
1062
1074
|
headers,
|
|
1063
1075
|
method: "POST",
|
|
1064
1076
|
url: context.url,
|
|
1077
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1078
|
+
retryDelay: context.retryDelay,
|
|
1079
|
+
flowControl: context.flowControl,
|
|
1065
1080
|
delay: isParallel ? void 0 : this.sleep
|
|
1066
1081
|
}
|
|
1067
1082
|
]);
|
|
@@ -1104,6 +1119,9 @@ var LazySleepUntilStep = class extends BaseLazyStep {
|
|
|
1104
1119
|
headers,
|
|
1105
1120
|
method: "POST",
|
|
1106
1121
|
url: context.url,
|
|
1122
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1123
|
+
retryDelay: context.retryDelay,
|
|
1124
|
+
flowControl: context.flowControl,
|
|
1107
1125
|
notBefore: isParallel ? void 0 : this.sleepUntil
|
|
1108
1126
|
}
|
|
1109
1127
|
]);
|
|
@@ -1115,17 +1133,19 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1115
1133
|
body;
|
|
1116
1134
|
headers;
|
|
1117
1135
|
retries;
|
|
1136
|
+
retryDelay;
|
|
1118
1137
|
timeout;
|
|
1119
1138
|
flowControl;
|
|
1120
1139
|
stepType = "Call";
|
|
1121
1140
|
allowUndefinedOut = false;
|
|
1122
|
-
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
1141
|
+
constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl) {
|
|
1123
1142
|
super(stepName);
|
|
1124
1143
|
this.url = url;
|
|
1125
1144
|
this.method = method;
|
|
1126
1145
|
this.body = body;
|
|
1127
1146
|
this.headers = headers;
|
|
1128
1147
|
this.retries = retries;
|
|
1148
|
+
this.retryDelay = retryDelay;
|
|
1129
1149
|
this.timeout = timeout;
|
|
1130
1150
|
this.flowControl = flowControl;
|
|
1131
1151
|
}
|
|
@@ -1200,6 +1220,9 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1200
1220
|
getHeaders({ context, telemetry, invokeCount, step }) {
|
|
1201
1221
|
const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
|
|
1202
1222
|
headers["Upstash-Retries"] = this.retries.toString();
|
|
1223
|
+
if (this.retryDelay) {
|
|
1224
|
+
headers["Upstash-Retry-Delay"] = this.retryDelay;
|
|
1225
|
+
}
|
|
1203
1226
|
headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
1204
1227
|
if (this.flowControl) {
|
|
1205
1228
|
const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
|
|
@@ -1221,7 +1244,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1221
1244
|
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1222
1245
|
"Upstash-Callback-Workflow-Init": "false",
|
|
1223
1246
|
"Upstash-Callback-Workflow-Url": context.url,
|
|
1224
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1247
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1225
1248
|
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1226
1249
|
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1227
1250
|
"Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
|
|
@@ -1239,7 +1262,10 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1239
1262
|
headers,
|
|
1240
1263
|
body: JSON.stringify(this.body),
|
|
1241
1264
|
method: this.method,
|
|
1242
|
-
url: this.url
|
|
1265
|
+
url: this.url,
|
|
1266
|
+
retries: DEFAULT_RETRIES === this.retries ? void 0 : this.retries,
|
|
1267
|
+
retryDelay: this.retryDelay,
|
|
1268
|
+
flowControl: this.flowControl
|
|
1243
1269
|
}
|
|
1244
1270
|
]);
|
|
1245
1271
|
}
|
|
@@ -1368,6 +1394,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1368
1394
|
headers = {},
|
|
1369
1395
|
workflowRunId,
|
|
1370
1396
|
retries,
|
|
1397
|
+
retryDelay,
|
|
1371
1398
|
flowControl
|
|
1372
1399
|
}) {
|
|
1373
1400
|
super(stepName);
|
|
@@ -1377,6 +1404,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1377
1404
|
headers,
|
|
1378
1405
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1379
1406
|
retries,
|
|
1407
|
+
retryDelay,
|
|
1380
1408
|
flowControl
|
|
1381
1409
|
};
|
|
1382
1410
|
const { workflowId } = workflow;
|
|
@@ -1421,6 +1449,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1421
1449
|
workflowUrl: context.url,
|
|
1422
1450
|
failureUrl: context.failureUrl,
|
|
1423
1451
|
retries: context.retries,
|
|
1452
|
+
retryDelay: context.retryDelay,
|
|
1424
1453
|
telemetry,
|
|
1425
1454
|
flowControl: context.flowControl,
|
|
1426
1455
|
useJSONContent: false
|
|
@@ -1446,11 +1475,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1446
1475
|
headers = {},
|
|
1447
1476
|
workflowRunId = getWorkflowRunId(),
|
|
1448
1477
|
retries,
|
|
1478
|
+
retryDelay,
|
|
1449
1479
|
flowControl
|
|
1450
1480
|
} = this.params;
|
|
1451
1481
|
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1452
1482
|
const {
|
|
1453
1483
|
retries: workflowRetries,
|
|
1484
|
+
retryDelay: workflowRetryDelay,
|
|
1454
1485
|
failureFunction,
|
|
1455
1486
|
failureUrl,
|
|
1456
1487
|
useJSONContent,
|
|
@@ -1462,6 +1493,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1462
1493
|
workflowRunId,
|
|
1463
1494
|
workflowUrl: newUrl,
|
|
1464
1495
|
retries: retries ?? workflowRetries,
|
|
1496
|
+
retryDelay: retryDelay ?? workflowRetryDelay,
|
|
1465
1497
|
telemetry,
|
|
1466
1498
|
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1467
1499
|
flowControl: flowControl ?? workflowFlowControl,
|
|
@@ -1528,6 +1560,7 @@ var WorkflowHeaders = class {
|
|
|
1528
1560
|
getHeaders() {
|
|
1529
1561
|
this.addBaseHeaders();
|
|
1530
1562
|
this.addRetries();
|
|
1563
|
+
this.addRetryDelay();
|
|
1531
1564
|
this.addFlowControl();
|
|
1532
1565
|
this.addUserHeaders();
|
|
1533
1566
|
this.addInvokeCount();
|
|
@@ -1541,7 +1574,7 @@ var WorkflowHeaders = class {
|
|
|
1541
1574
|
[WORKFLOW_INIT_HEADER]: this.initHeaderValue,
|
|
1542
1575
|
[WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
|
|
1543
1576
|
[WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
|
|
1544
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1577
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1545
1578
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1546
1579
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
|
|
1547
1580
|
...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
|
|
@@ -1573,6 +1606,16 @@ var WorkflowHeaders = class {
|
|
|
1573
1606
|
this.headers.failureHeaders["Retries"] = retries;
|
|
1574
1607
|
}
|
|
1575
1608
|
}
|
|
1609
|
+
addRetryDelay() {
|
|
1610
|
+
if (this.workflowConfig.retryDelay === void 0 || this.workflowConfig.retryDelay === "") {
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
const retryDelay = this.workflowConfig.retryDelay.toString();
|
|
1614
|
+
this.headers.workflowHeaders["Retry-Delay"] = retryDelay;
|
|
1615
|
+
if (this.workflowConfig.failureUrl) {
|
|
1616
|
+
this.headers.failureHeaders["Retry-Delay"] = retryDelay;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1576
1619
|
addFlowControl() {
|
|
1577
1620
|
if (!this.workflowConfig.flowControl) {
|
|
1578
1621
|
return;
|
|
@@ -1607,10 +1650,13 @@ var WorkflowHeaders = class {
|
|
|
1607
1650
|
this.headers.failureHeaders["Workflow-Init"] = "false";
|
|
1608
1651
|
this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
|
|
1609
1652
|
this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
|
|
1610
|
-
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
|
|
1653
|
+
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody,WF_DetectTrigger";
|
|
1611
1654
|
if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
|
|
1612
1655
|
this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
|
|
1613
1656
|
}
|
|
1657
|
+
if (this.workflowConfig.retryDelay !== void 0 && this.workflowConfig.retryDelay !== "") {
|
|
1658
|
+
this.headers.failureHeaders["Retry-Delay"] = this.workflowConfig.retryDelay.toString();
|
|
1659
|
+
}
|
|
1614
1660
|
}
|
|
1615
1661
|
addContentType() {
|
|
1616
1662
|
if (this.workflowConfig.useJSONContent) {
|
|
@@ -1692,6 +1738,7 @@ var submitParallelSteps = async ({
|
|
|
1692
1738
|
workflowUrl: context.url,
|
|
1693
1739
|
failureUrl: context.failureUrl,
|
|
1694
1740
|
retries: context.retries,
|
|
1741
|
+
retryDelay: context.retryDelay,
|
|
1695
1742
|
flowControl: context.flowControl,
|
|
1696
1743
|
telemetry
|
|
1697
1744
|
},
|
|
@@ -2112,7 +2159,7 @@ var BaseWorkflowApi = class {
|
|
|
2112
2159
|
*/
|
|
2113
2160
|
async callApi(stepName, settings) {
|
|
2114
2161
|
const { url, appendHeaders, method } = getProviderInfo(settings.api);
|
|
2115
|
-
const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
|
|
2162
|
+
const { method: userMethod, body, headers = {}, retries = 0, retryDelay, timeout } = settings;
|
|
2116
2163
|
return await this.context.call(stepName, {
|
|
2117
2164
|
url,
|
|
2118
2165
|
method: userMethod ?? method,
|
|
@@ -2122,6 +2169,7 @@ var BaseWorkflowApi = class {
|
|
|
2122
2169
|
...headers
|
|
2123
2170
|
},
|
|
2124
2171
|
retries,
|
|
2172
|
+
retryDelay,
|
|
2125
2173
|
timeout
|
|
2126
2174
|
});
|
|
2127
2175
|
}
|
|
@@ -2211,6 +2259,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
2211
2259
|
body,
|
|
2212
2260
|
timeout: agentCallParams?.timeout,
|
|
2213
2261
|
retries: agentCallParams?.retries,
|
|
2262
|
+
retryDelay: agentCallParams?.retryDelay,
|
|
2214
2263
|
flowControl: agentCallParams?.flowControl
|
|
2215
2264
|
});
|
|
2216
2265
|
const responseHeaders = new Headers(
|
|
@@ -2539,7 +2588,10 @@ var serveManyBase = ({
|
|
|
2539
2588
|
return new Response(
|
|
2540
2589
|
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
2541
2590
|
{
|
|
2542
|
-
status: 404
|
|
2591
|
+
status: 404,
|
|
2592
|
+
headers: {
|
|
2593
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
2594
|
+
}
|
|
2543
2595
|
}
|
|
2544
2596
|
);
|
|
2545
2597
|
}
|
|
@@ -2548,7 +2600,10 @@ var serveManyBase = ({
|
|
|
2548
2600
|
return new Response(
|
|
2549
2601
|
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
2550
2602
|
{
|
|
2551
|
-
status: 404
|
|
2603
|
+
status: 404,
|
|
2604
|
+
headers: {
|
|
2605
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
2606
|
+
}
|
|
2552
2607
|
}
|
|
2553
2608
|
);
|
|
2554
2609
|
}
|
|
@@ -2685,11 +2740,58 @@ var WorkflowContext = class {
|
|
|
2685
2740
|
* Number of retries
|
|
2686
2741
|
*/
|
|
2687
2742
|
retries;
|
|
2743
|
+
/**
|
|
2744
|
+
* Delay between retries.
|
|
2745
|
+
*
|
|
2746
|
+
* By default, the `retryDelay` is exponential backoff.
|
|
2747
|
+
* More details can be found in: https://upstash.com/docs/qstash/features/retry.
|
|
2748
|
+
*
|
|
2749
|
+
* The `retryDelay` option allows you to customize the delay (in milliseconds) between retry attempts when message delivery fails.
|
|
2750
|
+
*
|
|
2751
|
+
* You can use mathematical expressions and the following built-in functions to calculate the delay dynamically.
|
|
2752
|
+
* The special variable `retried` represents the current retry attempt count (starting from 0).
|
|
2753
|
+
*
|
|
2754
|
+
* Supported functions:
|
|
2755
|
+
* - `pow`
|
|
2756
|
+
* - `sqrt`
|
|
2757
|
+
* - `abs`
|
|
2758
|
+
* - `exp`
|
|
2759
|
+
* - `floor`
|
|
2760
|
+
* - `ceil`
|
|
2761
|
+
* - `round`
|
|
2762
|
+
* - `min`
|
|
2763
|
+
* - `max`
|
|
2764
|
+
*
|
|
2765
|
+
* Examples of valid `retryDelay` values:
|
|
2766
|
+
* ```ts
|
|
2767
|
+
* 1000 // 1 second
|
|
2768
|
+
* 1000 * (1 + retried) // 1 second multiplied by the current retry attempt
|
|
2769
|
+
* pow(2, retried) // 2 to the power of the current retry attempt
|
|
2770
|
+
* max(10, pow(2, retried)) // The greater of 10 or 2^retried
|
|
2771
|
+
* ```
|
|
2772
|
+
*/
|
|
2773
|
+
retryDelay;
|
|
2688
2774
|
/**
|
|
2689
2775
|
* Settings for controlling the number of active requests
|
|
2690
2776
|
* and number of requests per second with the same key.
|
|
2691
2777
|
*/
|
|
2692
2778
|
flowControl;
|
|
2779
|
+
/**
|
|
2780
|
+
* Label to apply to the workflow run.
|
|
2781
|
+
*
|
|
2782
|
+
* Can be used to filter the workflow run logs.
|
|
2783
|
+
*
|
|
2784
|
+
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2785
|
+
* with `client.trigger`:
|
|
2786
|
+
*
|
|
2787
|
+
* ```ts
|
|
2788
|
+
* await client.trigger({
|
|
2789
|
+
* url: "https://workflow-endpoint.com",
|
|
2790
|
+
* label: "my-label"
|
|
2791
|
+
* });
|
|
2792
|
+
* ```
|
|
2793
|
+
*/
|
|
2794
|
+
label;
|
|
2693
2795
|
constructor({
|
|
2694
2796
|
qstashClient,
|
|
2695
2797
|
workflowRunId,
|
|
@@ -2701,9 +2803,11 @@ var WorkflowContext = class {
|
|
|
2701
2803
|
initialPayload,
|
|
2702
2804
|
env,
|
|
2703
2805
|
retries,
|
|
2806
|
+
retryDelay,
|
|
2704
2807
|
telemetry,
|
|
2705
2808
|
invokeCount,
|
|
2706
|
-
flowControl
|
|
2809
|
+
flowControl,
|
|
2810
|
+
label
|
|
2707
2811
|
}) {
|
|
2708
2812
|
this.qstashClient = qstashClient;
|
|
2709
2813
|
this.workflowRunId = workflowRunId;
|
|
@@ -2714,7 +2818,9 @@ var WorkflowContext = class {
|
|
|
2714
2818
|
this.requestPayload = initialPayload;
|
|
2715
2819
|
this.env = env ?? {};
|
|
2716
2820
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2821
|
+
this.retryDelay = retryDelay;
|
|
2717
2822
|
this.flowControl = flowControl;
|
|
2823
|
+
this.label = label;
|
|
2718
2824
|
this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
|
|
2719
2825
|
}
|
|
2720
2826
|
/**
|
|
@@ -2795,6 +2901,7 @@ var WorkflowContext = class {
|
|
|
2795
2901
|
settings.body,
|
|
2796
2902
|
settings.headers || {},
|
|
2797
2903
|
settings.retries || 0,
|
|
2904
|
+
settings.retryDelay,
|
|
2798
2905
|
settings.timeout,
|
|
2799
2906
|
settings.flowControl ?? settings.workflow.options.flowControl
|
|
2800
2907
|
);
|
|
@@ -2805,6 +2912,7 @@ var WorkflowContext = class {
|
|
|
2805
2912
|
body,
|
|
2806
2913
|
headers = {},
|
|
2807
2914
|
retries = 0,
|
|
2915
|
+
retryDelay,
|
|
2808
2916
|
timeout,
|
|
2809
2917
|
flowControl
|
|
2810
2918
|
} = settings;
|
|
@@ -2815,6 +2923,7 @@ var WorkflowContext = class {
|
|
|
2815
2923
|
body,
|
|
2816
2924
|
headers,
|
|
2817
2925
|
retries,
|
|
2926
|
+
retryDelay,
|
|
2818
2927
|
timeout,
|
|
2819
2928
|
flowControl
|
|
2820
2929
|
);
|
|
@@ -2825,7 +2934,7 @@ var WorkflowContext = class {
|
|
|
2825
2934
|
* Pauses workflow execution until a specific event occurs or a timeout is reached.
|
|
2826
2935
|
*
|
|
2827
2936
|
*```ts
|
|
2828
|
-
* const result = await workflow.waitForEvent("payment-confirmed", {
|
|
2937
|
+
* const result = await workflow.waitForEvent("payment-confirmed", "payment.confirmed", {
|
|
2829
2938
|
* timeout: "5m"
|
|
2830
2939
|
* });
|
|
2831
2940
|
*```
|
|
@@ -2851,7 +2960,7 @@ var WorkflowContext = class {
|
|
|
2851
2960
|
* @param stepName
|
|
2852
2961
|
* @param eventId - Unique identifier for the event to wait for
|
|
2853
2962
|
* @param options - Configuration options.
|
|
2854
|
-
* @returns `{ timeout: boolean, eventData:
|
|
2963
|
+
* @returns `{ timeout: boolean, eventData: TEventData }`.
|
|
2855
2964
|
* The `timeout` property specifies if the workflow has timed out. The `eventData`
|
|
2856
2965
|
* is the data passed when notifying this workflow of an event.
|
|
2857
2966
|
*/
|
|
@@ -3011,7 +3120,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3011
3120
|
initialPayload: context.requestPayload,
|
|
3012
3121
|
env: context.env,
|
|
3013
3122
|
retries: context.retries,
|
|
3014
|
-
|
|
3123
|
+
retryDelay: context.retryDelay,
|
|
3124
|
+
flowControl: context.flowControl,
|
|
3125
|
+
label: context.label
|
|
3015
3126
|
});
|
|
3016
3127
|
try {
|
|
3017
3128
|
await routeFunction(disabledContext);
|
|
@@ -3019,6 +3130,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3019
3130
|
if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
|
|
3020
3131
|
return ok("step-found");
|
|
3021
3132
|
}
|
|
3133
|
+
console.warn(
|
|
3134
|
+
"Upstash Workflow: Received an error while authorizing request. Please avoid throwing errors before the first step of your workflow."
|
|
3135
|
+
);
|
|
3022
3136
|
return err(error);
|
|
3023
3137
|
}
|
|
3024
3138
|
return ok("run-ended");
|
|
@@ -3160,9 +3274,9 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
3160
3274
|
};
|
|
3161
3275
|
}
|
|
3162
3276
|
};
|
|
3163
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
3277
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, retryDelay, flowControl, debug) => {
|
|
3164
3278
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
3165
|
-
return ok("not-failure-callback");
|
|
3279
|
+
return ok({ result: "not-failure-callback" });
|
|
3166
3280
|
}
|
|
3167
3281
|
if (!failureFunction) {
|
|
3168
3282
|
return err(
|
|
@@ -3185,20 +3299,23 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3185
3299
|
if (!errorMessage) {
|
|
3186
3300
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3187
3301
|
}
|
|
3302
|
+
const userHeaders = recreateUserHeaders(request.headers);
|
|
3188
3303
|
const workflowContext = new WorkflowContext({
|
|
3189
3304
|
qstashClient,
|
|
3190
3305
|
workflowRunId,
|
|
3191
3306
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
3192
|
-
headers:
|
|
3307
|
+
headers: userHeaders,
|
|
3193
3308
|
steps: [],
|
|
3194
3309
|
url,
|
|
3195
3310
|
failureUrl: url,
|
|
3196
3311
|
debug,
|
|
3197
3312
|
env,
|
|
3198
3313
|
retries,
|
|
3314
|
+
retryDelay,
|
|
3199
3315
|
flowControl,
|
|
3200
|
-
telemetry: void 0
|
|
3316
|
+
telemetry: void 0,
|
|
3201
3317
|
// not going to make requests in authentication check
|
|
3318
|
+
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0
|
|
3202
3319
|
});
|
|
3203
3320
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3204
3321
|
routeFunction,
|
|
@@ -3210,16 +3327,16 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3210
3327
|
} else if (authCheck.value === "run-ended") {
|
|
3211
3328
|
return err(new WorkflowError("Not authorized to run the failure function."));
|
|
3212
3329
|
}
|
|
3213
|
-
await failureFunction({
|
|
3330
|
+
const failureResponse = await failureFunction({
|
|
3214
3331
|
context: workflowContext,
|
|
3215
3332
|
failStatus: status,
|
|
3216
3333
|
failResponse: errorMessage,
|
|
3217
3334
|
failHeaders: header
|
|
3218
3335
|
});
|
|
3336
|
+
return ok({ result: "is-failure-callback", response: failureResponse });
|
|
3219
3337
|
} catch (error) {
|
|
3220
3338
|
return err(error);
|
|
3221
3339
|
}
|
|
3222
|
-
return ok("is-failure-callback");
|
|
3223
3340
|
};
|
|
3224
3341
|
|
|
3225
3342
|
// src/serve/options.ts
|
|
@@ -3235,8 +3352,8 @@ var processOptions = (options) => {
|
|
|
3235
3352
|
baseUrl: environment.QSTASH_URL,
|
|
3236
3353
|
token: environment.QSTASH_TOKEN
|
|
3237
3354
|
}),
|
|
3238
|
-
onStepFinish: (workflowRunId,
|
|
3239
|
-
if (
|
|
3355
|
+
onStepFinish: (workflowRunId, _finishCondition, detailedFinishCondition) => {
|
|
3356
|
+
if (detailedFinishCondition?.condition === "auth-fail") {
|
|
3240
3357
|
console.error(AUTH_FAIL_MESSAGE);
|
|
3241
3358
|
return new Response(
|
|
3242
3359
|
JSON.stringify({
|
|
@@ -3244,19 +3361,33 @@ var processOptions = (options) => {
|
|
|
3244
3361
|
workflowRunId
|
|
3245
3362
|
}),
|
|
3246
3363
|
{
|
|
3247
|
-
status: 400
|
|
3364
|
+
status: 400,
|
|
3365
|
+
headers: {
|
|
3366
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3367
|
+
}
|
|
3248
3368
|
}
|
|
3249
3369
|
);
|
|
3250
|
-
} else if (
|
|
3251
|
-
return new Response(JSON.stringify(formatWorkflowError(
|
|
3370
|
+
} else if (detailedFinishCondition?.condition === "non-retryable-error") {
|
|
3371
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3252
3372
|
headers: {
|
|
3253
|
-
"Upstash-NonRetryable-Error": "true"
|
|
3373
|
+
"Upstash-NonRetryable-Error": "true",
|
|
3374
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3254
3375
|
},
|
|
3255
3376
|
status: 489
|
|
3256
3377
|
});
|
|
3378
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3379
|
+
return new Response(detailedFinishCondition.result ?? void 0, {
|
|
3380
|
+
status: 200,
|
|
3381
|
+
headers: {
|
|
3382
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3383
|
+
}
|
|
3384
|
+
});
|
|
3257
3385
|
}
|
|
3258
3386
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3259
|
-
status: 200
|
|
3387
|
+
status: 200,
|
|
3388
|
+
headers: {
|
|
3389
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3390
|
+
}
|
|
3260
3391
|
});
|
|
3261
3392
|
},
|
|
3262
3393
|
initialPayloadParser: (initialRequest) => {
|
|
@@ -3330,6 +3461,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3330
3461
|
baseUrl,
|
|
3331
3462
|
env,
|
|
3332
3463
|
retries,
|
|
3464
|
+
retryDelay,
|
|
3333
3465
|
useJSONContent,
|
|
3334
3466
|
disableTelemetry,
|
|
3335
3467
|
flowControl,
|
|
@@ -3360,10 +3492,14 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3360
3492
|
debug
|
|
3361
3493
|
);
|
|
3362
3494
|
if (workflowRunEnded) {
|
|
3363
|
-
return onStepFinish(workflowRunId, "workflow-already-ended"
|
|
3495
|
+
return onStepFinish(workflowRunId, "workflow-already-ended", {
|
|
3496
|
+
condition: "workflow-already-ended"
|
|
3497
|
+
});
|
|
3364
3498
|
}
|
|
3365
3499
|
if (isLastDuplicate) {
|
|
3366
|
-
return onStepFinish(workflowRunId, "duplicate-step"
|
|
3500
|
+
return onStepFinish(workflowRunId, "duplicate-step", {
|
|
3501
|
+
condition: "duplicate-step"
|
|
3502
|
+
});
|
|
3367
3503
|
}
|
|
3368
3504
|
const failureCheck = await handleFailure(
|
|
3369
3505
|
request,
|
|
@@ -3374,16 +3510,21 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3374
3510
|
failureFunction,
|
|
3375
3511
|
env,
|
|
3376
3512
|
retries,
|
|
3513
|
+
retryDelay,
|
|
3377
3514
|
flowControl,
|
|
3378
3515
|
debug
|
|
3379
3516
|
);
|
|
3380
3517
|
if (failureCheck.isErr()) {
|
|
3381
3518
|
throw failureCheck.error;
|
|
3382
|
-
} else if (failureCheck.value === "is-failure-callback") {
|
|
3519
|
+
} else if (failureCheck.value.result === "is-failure-callback") {
|
|
3383
3520
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
3384
|
-
return onStepFinish(workflowRunId, "failure-callback"
|
|
3521
|
+
return onStepFinish(workflowRunId, "failure-callback", {
|
|
3522
|
+
condition: "failure-callback",
|
|
3523
|
+
result: failureCheck.value.response
|
|
3524
|
+
});
|
|
3385
3525
|
}
|
|
3386
3526
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3527
|
+
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3387
3528
|
const workflowContext = new WorkflowContext({
|
|
3388
3529
|
qstashClient,
|
|
3389
3530
|
workflowRunId,
|
|
@@ -3395,9 +3536,11 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3395
3536
|
debug,
|
|
3396
3537
|
env,
|
|
3397
3538
|
retries,
|
|
3539
|
+
retryDelay,
|
|
3398
3540
|
telemetry,
|
|
3399
3541
|
invokeCount,
|
|
3400
|
-
flowControl
|
|
3542
|
+
flowControl,
|
|
3543
|
+
label
|
|
3401
3544
|
});
|
|
3402
3545
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3403
3546
|
routeFunction,
|
|
@@ -3410,7 +3553,8 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3410
3553
|
await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
|
|
3411
3554
|
return onStepFinish(
|
|
3412
3555
|
isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
|
|
3413
|
-
"auth-fail"
|
|
3556
|
+
"auth-fail",
|
|
3557
|
+
{ condition: "auth-fail" }
|
|
3414
3558
|
);
|
|
3415
3559
|
}
|
|
3416
3560
|
const callReturnCheck = await handleThirdPartyCallResult({
|
|
@@ -3420,6 +3564,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3420
3564
|
workflowUrl,
|
|
3421
3565
|
failureUrl: workflowFailureUrl,
|
|
3422
3566
|
retries,
|
|
3567
|
+
retryDelay,
|
|
3423
3568
|
flowControl,
|
|
3424
3569
|
telemetry,
|
|
3425
3570
|
debug
|
|
@@ -3447,19 +3592,28 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3447
3592
|
debug
|
|
3448
3593
|
});
|
|
3449
3594
|
if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
|
|
3450
|
-
return onStepFinish(workflowRunId, result.value
|
|
3595
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
3596
|
+
condition: "non-retryable-error",
|
|
3597
|
+
result: result.value
|
|
3598
|
+
});
|
|
3451
3599
|
}
|
|
3452
3600
|
if (result.isErr()) {
|
|
3453
3601
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3454
3602
|
throw result.error;
|
|
3455
3603
|
}
|
|
3456
3604
|
await debug?.log("INFO", "RESPONSE_WORKFLOW");
|
|
3457
|
-
return onStepFinish(workflowContext.workflowRunId, "success"
|
|
3605
|
+
return onStepFinish(workflowContext.workflowRunId, "success", {
|
|
3606
|
+
condition: "success"
|
|
3607
|
+
});
|
|
3458
3608
|
} else if (callReturnCheck.value === "workflow-ended") {
|
|
3459
|
-
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended"
|
|
3609
|
+
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended", {
|
|
3610
|
+
condition: "workflow-already-ended"
|
|
3611
|
+
});
|
|
3460
3612
|
}
|
|
3461
3613
|
await debug?.log("INFO", "RESPONSE_DEFAULT");
|
|
3462
|
-
return onStepFinish("no-workflow-id", "fromCallback"
|
|
3614
|
+
return onStepFinish("no-workflow-id", "fromCallback", {
|
|
3615
|
+
condition: "fromCallback"
|
|
3616
|
+
});
|
|
3463
3617
|
};
|
|
3464
3618
|
const safeHandler = async (request) => {
|
|
3465
3619
|
try {
|
|
@@ -3474,11 +3628,17 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3474
3628
|
Original error: '${formattedError.message}'`;
|
|
3475
3629
|
console.error(errorMessage);
|
|
3476
3630
|
return new Response(errorMessage, {
|
|
3477
|
-
status: 500
|
|
3631
|
+
status: 500,
|
|
3632
|
+
headers: {
|
|
3633
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3634
|
+
}
|
|
3478
3635
|
});
|
|
3479
3636
|
}
|
|
3480
3637
|
return new Response(JSON.stringify(formattedError), {
|
|
3481
|
-
status: 500
|
|
3638
|
+
status: 500,
|
|
3639
|
+
headers: {
|
|
3640
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3641
|
+
}
|
|
3482
3642
|
});
|
|
3483
3643
|
}
|
|
3484
3644
|
};
|
|
@@ -3546,6 +3706,9 @@ var servePagesRouter = (routeFunction, options) => {
|
|
|
3546
3706
|
method: "POST"
|
|
3547
3707
|
});
|
|
3548
3708
|
const response = await serveHandler(request);
|
|
3709
|
+
for (const [key, value] of response.headers.entries()) {
|
|
3710
|
+
res.setHeader(key, value);
|
|
3711
|
+
}
|
|
3549
3712
|
res.status(response.status).json(await response.json());
|
|
3550
3713
|
};
|
|
3551
3714
|
return {
|