@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/index.js
CHANGED
|
@@ -99,12 +99,13 @@ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
|
99
99
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
100
100
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
101
101
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
102
|
+
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
102
103
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
103
104
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
104
105
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
105
106
|
var NO_CONCURRENCY = 1;
|
|
106
107
|
var DEFAULT_RETRIES = 3;
|
|
107
|
-
var VERSION = "v0.2.
|
|
108
|
+
var VERSION = "v0.2.18";
|
|
108
109
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
109
110
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
110
111
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -634,6 +635,7 @@ var triggerFirstInvocation = async (params) => {
|
|
|
634
635
|
workflowUrl: workflowContext.url,
|
|
635
636
|
failureUrl: workflowContext.failureUrl,
|
|
636
637
|
retries: workflowContext.retries,
|
|
638
|
+
retryDelay: workflowContext.retryDelay,
|
|
637
639
|
telemetry,
|
|
638
640
|
flowControl: workflowContext.flowControl,
|
|
639
641
|
useJSONContent: useJSONContent ?? false
|
|
@@ -647,6 +649,9 @@ var triggerFirstInvocation = async (params) => {
|
|
|
647
649
|
if (useJSONContent) {
|
|
648
650
|
headers["content-type"] = "application/json";
|
|
649
651
|
}
|
|
652
|
+
if (workflowContext.label) {
|
|
653
|
+
headers[WORKFLOW_LABEL_HEADER] = workflowContext.label;
|
|
654
|
+
}
|
|
650
655
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
651
656
|
return {
|
|
652
657
|
headers,
|
|
@@ -747,10 +752,11 @@ var recreateUserHeaders = (headers) => {
|
|
|
747
752
|
const pairs = headers.entries();
|
|
748
753
|
for (const [header, value] of pairs) {
|
|
749
754
|
const headerLowerCase = header.toLowerCase();
|
|
750
|
-
|
|
755
|
+
const isUserHeader = !headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
751
756
|
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
752
757
|
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
753
|
-
headerLowerCase !== "render-proxy-ttl")
|
|
758
|
+
headerLowerCase !== "render-proxy-ttl" || headerLowerCase === WORKFLOW_LABEL_HEADER.toLocaleLowerCase();
|
|
759
|
+
if (isUserHeader) {
|
|
754
760
|
filteredHeaders.append(header, value);
|
|
755
761
|
}
|
|
756
762
|
}
|
|
@@ -763,6 +769,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
763
769
|
workflowUrl,
|
|
764
770
|
failureUrl,
|
|
765
771
|
retries,
|
|
772
|
+
retryDelay,
|
|
766
773
|
telemetry,
|
|
767
774
|
flowControl,
|
|
768
775
|
debug
|
|
@@ -833,6 +840,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
833
840
|
workflowUrl,
|
|
834
841
|
failureUrl,
|
|
835
842
|
retries,
|
|
843
|
+
retryDelay,
|
|
836
844
|
telemetry,
|
|
837
845
|
flowControl
|
|
838
846
|
},
|
|
@@ -983,7 +991,8 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
983
991
|
workflowRunId: context.workflowRunId,
|
|
984
992
|
workflowUrl: context.url,
|
|
985
993
|
failureUrl: context.failureUrl,
|
|
986
|
-
retries: context.retries,
|
|
994
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
995
|
+
retryDelay: context.retryDelay,
|
|
987
996
|
useJSONContent: false,
|
|
988
997
|
telemetry,
|
|
989
998
|
flowControl: context.flowControl
|
|
@@ -1002,6 +1011,9 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1002
1011
|
body,
|
|
1003
1012
|
headers,
|
|
1004
1013
|
method: "POST",
|
|
1014
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1015
|
+
retryDelay: context.retryDelay,
|
|
1016
|
+
flowControl: context.flowControl,
|
|
1005
1017
|
url: context.url
|
|
1006
1018
|
}
|
|
1007
1019
|
]);
|
|
@@ -1072,6 +1084,9 @@ var LazySleepStep = class extends BaseLazyStep {
|
|
|
1072
1084
|
headers,
|
|
1073
1085
|
method: "POST",
|
|
1074
1086
|
url: context.url,
|
|
1087
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1088
|
+
retryDelay: context.retryDelay,
|
|
1089
|
+
flowControl: context.flowControl,
|
|
1075
1090
|
delay: isParallel ? void 0 : this.sleep
|
|
1076
1091
|
}
|
|
1077
1092
|
]);
|
|
@@ -1114,6 +1129,9 @@ var LazySleepUntilStep = class extends BaseLazyStep {
|
|
|
1114
1129
|
headers,
|
|
1115
1130
|
method: "POST",
|
|
1116
1131
|
url: context.url,
|
|
1132
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1133
|
+
retryDelay: context.retryDelay,
|
|
1134
|
+
flowControl: context.flowControl,
|
|
1117
1135
|
notBefore: isParallel ? void 0 : this.sleepUntil
|
|
1118
1136
|
}
|
|
1119
1137
|
]);
|
|
@@ -1125,17 +1143,19 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1125
1143
|
body;
|
|
1126
1144
|
headers;
|
|
1127
1145
|
retries;
|
|
1146
|
+
retryDelay;
|
|
1128
1147
|
timeout;
|
|
1129
1148
|
flowControl;
|
|
1130
1149
|
stepType = "Call";
|
|
1131
1150
|
allowUndefinedOut = false;
|
|
1132
|
-
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
1151
|
+
constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl) {
|
|
1133
1152
|
super(stepName);
|
|
1134
1153
|
this.url = url;
|
|
1135
1154
|
this.method = method;
|
|
1136
1155
|
this.body = body;
|
|
1137
1156
|
this.headers = headers;
|
|
1138
1157
|
this.retries = retries;
|
|
1158
|
+
this.retryDelay = retryDelay;
|
|
1139
1159
|
this.timeout = timeout;
|
|
1140
1160
|
this.flowControl = flowControl;
|
|
1141
1161
|
}
|
|
@@ -1210,6 +1230,9 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1210
1230
|
getHeaders({ context, telemetry, invokeCount, step }) {
|
|
1211
1231
|
const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
|
|
1212
1232
|
headers["Upstash-Retries"] = this.retries.toString();
|
|
1233
|
+
if (this.retryDelay) {
|
|
1234
|
+
headers["Upstash-Retry-Delay"] = this.retryDelay;
|
|
1235
|
+
}
|
|
1213
1236
|
headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
1214
1237
|
if (this.flowControl) {
|
|
1215
1238
|
const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
|
|
@@ -1231,7 +1254,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1231
1254
|
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1232
1255
|
"Upstash-Callback-Workflow-Init": "false",
|
|
1233
1256
|
"Upstash-Callback-Workflow-Url": context.url,
|
|
1234
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1257
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1235
1258
|
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1236
1259
|
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1237
1260
|
"Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
|
|
@@ -1249,7 +1272,10 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1249
1272
|
headers,
|
|
1250
1273
|
body: JSON.stringify(this.body),
|
|
1251
1274
|
method: this.method,
|
|
1252
|
-
url: this.url
|
|
1275
|
+
url: this.url,
|
|
1276
|
+
retries: DEFAULT_RETRIES === this.retries ? void 0 : this.retries,
|
|
1277
|
+
retryDelay: this.retryDelay,
|
|
1278
|
+
flowControl: this.flowControl
|
|
1253
1279
|
}
|
|
1254
1280
|
]);
|
|
1255
1281
|
}
|
|
@@ -1378,6 +1404,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1378
1404
|
headers = {},
|
|
1379
1405
|
workflowRunId,
|
|
1380
1406
|
retries,
|
|
1407
|
+
retryDelay,
|
|
1381
1408
|
flowControl
|
|
1382
1409
|
}) {
|
|
1383
1410
|
super(stepName);
|
|
@@ -1387,6 +1414,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1387
1414
|
headers,
|
|
1388
1415
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1389
1416
|
retries,
|
|
1417
|
+
retryDelay,
|
|
1390
1418
|
flowControl
|
|
1391
1419
|
};
|
|
1392
1420
|
const { workflowId } = workflow;
|
|
@@ -1431,6 +1459,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1431
1459
|
workflowUrl: context.url,
|
|
1432
1460
|
failureUrl: context.failureUrl,
|
|
1433
1461
|
retries: context.retries,
|
|
1462
|
+
retryDelay: context.retryDelay,
|
|
1434
1463
|
telemetry,
|
|
1435
1464
|
flowControl: context.flowControl,
|
|
1436
1465
|
useJSONContent: false
|
|
@@ -1456,11 +1485,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1456
1485
|
headers = {},
|
|
1457
1486
|
workflowRunId = getWorkflowRunId(),
|
|
1458
1487
|
retries,
|
|
1488
|
+
retryDelay,
|
|
1459
1489
|
flowControl
|
|
1460
1490
|
} = this.params;
|
|
1461
1491
|
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1462
1492
|
const {
|
|
1463
1493
|
retries: workflowRetries,
|
|
1494
|
+
retryDelay: workflowRetryDelay,
|
|
1464
1495
|
failureFunction,
|
|
1465
1496
|
failureUrl,
|
|
1466
1497
|
useJSONContent,
|
|
@@ -1472,6 +1503,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1472
1503
|
workflowRunId,
|
|
1473
1504
|
workflowUrl: newUrl,
|
|
1474
1505
|
retries: retries ?? workflowRetries,
|
|
1506
|
+
retryDelay: retryDelay ?? workflowRetryDelay,
|
|
1475
1507
|
telemetry,
|
|
1476
1508
|
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1477
1509
|
flowControl: flowControl ?? workflowFlowControl,
|
|
@@ -1538,6 +1570,7 @@ var WorkflowHeaders = class {
|
|
|
1538
1570
|
getHeaders() {
|
|
1539
1571
|
this.addBaseHeaders();
|
|
1540
1572
|
this.addRetries();
|
|
1573
|
+
this.addRetryDelay();
|
|
1541
1574
|
this.addFlowControl();
|
|
1542
1575
|
this.addUserHeaders();
|
|
1543
1576
|
this.addInvokeCount();
|
|
@@ -1551,7 +1584,7 @@ var WorkflowHeaders = class {
|
|
|
1551
1584
|
[WORKFLOW_INIT_HEADER]: this.initHeaderValue,
|
|
1552
1585
|
[WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
|
|
1553
1586
|
[WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
|
|
1554
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1587
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1555
1588
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1556
1589
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
|
|
1557
1590
|
...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
|
|
@@ -1583,6 +1616,16 @@ var WorkflowHeaders = class {
|
|
|
1583
1616
|
this.headers.failureHeaders["Retries"] = retries;
|
|
1584
1617
|
}
|
|
1585
1618
|
}
|
|
1619
|
+
addRetryDelay() {
|
|
1620
|
+
if (this.workflowConfig.retryDelay === void 0 || this.workflowConfig.retryDelay === "") {
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
const retryDelay = this.workflowConfig.retryDelay.toString();
|
|
1624
|
+
this.headers.workflowHeaders["Retry-Delay"] = retryDelay;
|
|
1625
|
+
if (this.workflowConfig.failureUrl) {
|
|
1626
|
+
this.headers.failureHeaders["Retry-Delay"] = retryDelay;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1586
1629
|
addFlowControl() {
|
|
1587
1630
|
if (!this.workflowConfig.flowControl) {
|
|
1588
1631
|
return;
|
|
@@ -1617,10 +1660,13 @@ var WorkflowHeaders = class {
|
|
|
1617
1660
|
this.headers.failureHeaders["Workflow-Init"] = "false";
|
|
1618
1661
|
this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
|
|
1619
1662
|
this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
|
|
1620
|
-
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
|
|
1663
|
+
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody,WF_DetectTrigger";
|
|
1621
1664
|
if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
|
|
1622
1665
|
this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
|
|
1623
1666
|
}
|
|
1667
|
+
if (this.workflowConfig.retryDelay !== void 0 && this.workflowConfig.retryDelay !== "") {
|
|
1668
|
+
this.headers.failureHeaders["Retry-Delay"] = this.workflowConfig.retryDelay.toString();
|
|
1669
|
+
}
|
|
1624
1670
|
}
|
|
1625
1671
|
addContentType() {
|
|
1626
1672
|
if (this.workflowConfig.useJSONContent) {
|
|
@@ -1702,6 +1748,7 @@ var submitParallelSteps = async ({
|
|
|
1702
1748
|
workflowUrl: context.url,
|
|
1703
1749
|
failureUrl: context.failureUrl,
|
|
1704
1750
|
retries: context.retries,
|
|
1751
|
+
retryDelay: context.retryDelay,
|
|
1705
1752
|
flowControl: context.flowControl,
|
|
1706
1753
|
telemetry
|
|
1707
1754
|
},
|
|
@@ -2122,7 +2169,7 @@ var BaseWorkflowApi = class {
|
|
|
2122
2169
|
*/
|
|
2123
2170
|
async callApi(stepName, settings) {
|
|
2124
2171
|
const { url, appendHeaders, method } = getProviderInfo(settings.api);
|
|
2125
|
-
const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
|
|
2172
|
+
const { method: userMethod, body, headers = {}, retries = 0, retryDelay, timeout } = settings;
|
|
2126
2173
|
return await this.context.call(stepName, {
|
|
2127
2174
|
url,
|
|
2128
2175
|
method: userMethod ?? method,
|
|
@@ -2132,6 +2179,7 @@ var BaseWorkflowApi = class {
|
|
|
2132
2179
|
...headers
|
|
2133
2180
|
},
|
|
2134
2181
|
retries,
|
|
2182
|
+
retryDelay,
|
|
2135
2183
|
timeout
|
|
2136
2184
|
});
|
|
2137
2185
|
}
|
|
@@ -2221,6 +2269,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
2221
2269
|
body,
|
|
2222
2270
|
timeout: agentCallParams?.timeout,
|
|
2223
2271
|
retries: agentCallParams?.retries,
|
|
2272
|
+
retryDelay: agentCallParams?.retryDelay,
|
|
2224
2273
|
flowControl: agentCallParams?.flowControl
|
|
2225
2274
|
});
|
|
2226
2275
|
const responseHeaders = new Headers(
|
|
@@ -2665,11 +2714,58 @@ var WorkflowContext = class {
|
|
|
2665
2714
|
* Number of retries
|
|
2666
2715
|
*/
|
|
2667
2716
|
retries;
|
|
2717
|
+
/**
|
|
2718
|
+
* Delay between retries.
|
|
2719
|
+
*
|
|
2720
|
+
* By default, the `retryDelay` is exponential backoff.
|
|
2721
|
+
* More details can be found in: https://upstash.com/docs/qstash/features/retry.
|
|
2722
|
+
*
|
|
2723
|
+
* The `retryDelay` option allows you to customize the delay (in milliseconds) between retry attempts when message delivery fails.
|
|
2724
|
+
*
|
|
2725
|
+
* You can use mathematical expressions and the following built-in functions to calculate the delay dynamically.
|
|
2726
|
+
* The special variable `retried` represents the current retry attempt count (starting from 0).
|
|
2727
|
+
*
|
|
2728
|
+
* Supported functions:
|
|
2729
|
+
* - `pow`
|
|
2730
|
+
* - `sqrt`
|
|
2731
|
+
* - `abs`
|
|
2732
|
+
* - `exp`
|
|
2733
|
+
* - `floor`
|
|
2734
|
+
* - `ceil`
|
|
2735
|
+
* - `round`
|
|
2736
|
+
* - `min`
|
|
2737
|
+
* - `max`
|
|
2738
|
+
*
|
|
2739
|
+
* Examples of valid `retryDelay` values:
|
|
2740
|
+
* ```ts
|
|
2741
|
+
* 1000 // 1 second
|
|
2742
|
+
* 1000 * (1 + retried) // 1 second multiplied by the current retry attempt
|
|
2743
|
+
* pow(2, retried) // 2 to the power of the current retry attempt
|
|
2744
|
+
* max(10, pow(2, retried)) // The greater of 10 or 2^retried
|
|
2745
|
+
* ```
|
|
2746
|
+
*/
|
|
2747
|
+
retryDelay;
|
|
2668
2748
|
/**
|
|
2669
2749
|
* Settings for controlling the number of active requests
|
|
2670
2750
|
* and number of requests per second with the same key.
|
|
2671
2751
|
*/
|
|
2672
2752
|
flowControl;
|
|
2753
|
+
/**
|
|
2754
|
+
* Label to apply to the workflow run.
|
|
2755
|
+
*
|
|
2756
|
+
* Can be used to filter the workflow run logs.
|
|
2757
|
+
*
|
|
2758
|
+
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2759
|
+
* with `client.trigger`:
|
|
2760
|
+
*
|
|
2761
|
+
* ```ts
|
|
2762
|
+
* await client.trigger({
|
|
2763
|
+
* url: "https://workflow-endpoint.com",
|
|
2764
|
+
* label: "my-label"
|
|
2765
|
+
* });
|
|
2766
|
+
* ```
|
|
2767
|
+
*/
|
|
2768
|
+
label;
|
|
2673
2769
|
constructor({
|
|
2674
2770
|
qstashClient,
|
|
2675
2771
|
workflowRunId,
|
|
@@ -2681,9 +2777,11 @@ var WorkflowContext = class {
|
|
|
2681
2777
|
initialPayload,
|
|
2682
2778
|
env,
|
|
2683
2779
|
retries,
|
|
2780
|
+
retryDelay,
|
|
2684
2781
|
telemetry,
|
|
2685
2782
|
invokeCount,
|
|
2686
|
-
flowControl
|
|
2783
|
+
flowControl,
|
|
2784
|
+
label
|
|
2687
2785
|
}) {
|
|
2688
2786
|
this.qstashClient = qstashClient;
|
|
2689
2787
|
this.workflowRunId = workflowRunId;
|
|
@@ -2694,7 +2792,9 @@ var WorkflowContext = class {
|
|
|
2694
2792
|
this.requestPayload = initialPayload;
|
|
2695
2793
|
this.env = env ?? {};
|
|
2696
2794
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2795
|
+
this.retryDelay = retryDelay;
|
|
2697
2796
|
this.flowControl = flowControl;
|
|
2797
|
+
this.label = label;
|
|
2698
2798
|
this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
|
|
2699
2799
|
}
|
|
2700
2800
|
/**
|
|
@@ -2775,6 +2875,7 @@ var WorkflowContext = class {
|
|
|
2775
2875
|
settings.body,
|
|
2776
2876
|
settings.headers || {},
|
|
2777
2877
|
settings.retries || 0,
|
|
2878
|
+
settings.retryDelay,
|
|
2778
2879
|
settings.timeout,
|
|
2779
2880
|
settings.flowControl ?? settings.workflow.options.flowControl
|
|
2780
2881
|
);
|
|
@@ -2785,6 +2886,7 @@ var WorkflowContext = class {
|
|
|
2785
2886
|
body,
|
|
2786
2887
|
headers = {},
|
|
2787
2888
|
retries = 0,
|
|
2889
|
+
retryDelay,
|
|
2788
2890
|
timeout,
|
|
2789
2891
|
flowControl
|
|
2790
2892
|
} = settings;
|
|
@@ -2795,6 +2897,7 @@ var WorkflowContext = class {
|
|
|
2795
2897
|
body,
|
|
2796
2898
|
headers,
|
|
2797
2899
|
retries,
|
|
2900
|
+
retryDelay,
|
|
2798
2901
|
timeout,
|
|
2799
2902
|
flowControl
|
|
2800
2903
|
);
|
|
@@ -2805,7 +2908,7 @@ var WorkflowContext = class {
|
|
|
2805
2908
|
* Pauses workflow execution until a specific event occurs or a timeout is reached.
|
|
2806
2909
|
*
|
|
2807
2910
|
*```ts
|
|
2808
|
-
* const result = await workflow.waitForEvent("payment-confirmed", {
|
|
2911
|
+
* const result = await workflow.waitForEvent("payment-confirmed", "payment.confirmed", {
|
|
2809
2912
|
* timeout: "5m"
|
|
2810
2913
|
* });
|
|
2811
2914
|
*```
|
|
@@ -2831,7 +2934,7 @@ var WorkflowContext = class {
|
|
|
2831
2934
|
* @param stepName
|
|
2832
2935
|
* @param eventId - Unique identifier for the event to wait for
|
|
2833
2936
|
* @param options - Configuration options.
|
|
2834
|
-
* @returns `{ timeout: boolean, eventData:
|
|
2937
|
+
* @returns `{ timeout: boolean, eventData: TEventData }`.
|
|
2835
2938
|
* The `timeout` property specifies if the workflow has timed out. The `eventData`
|
|
2836
2939
|
* is the data passed when notifying this workflow of an event.
|
|
2837
2940
|
*/
|
|
@@ -2991,7 +3094,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2991
3094
|
initialPayload: context.requestPayload,
|
|
2992
3095
|
env: context.env,
|
|
2993
3096
|
retries: context.retries,
|
|
2994
|
-
|
|
3097
|
+
retryDelay: context.retryDelay,
|
|
3098
|
+
flowControl: context.flowControl,
|
|
3099
|
+
label: context.label
|
|
2995
3100
|
});
|
|
2996
3101
|
try {
|
|
2997
3102
|
await routeFunction(disabledContext);
|
|
@@ -2999,6 +3104,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2999
3104
|
if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
|
|
3000
3105
|
return ok("step-found");
|
|
3001
3106
|
}
|
|
3107
|
+
console.warn(
|
|
3108
|
+
"Upstash Workflow: Received an error while authorizing request. Please avoid throwing errors before the first step of your workflow."
|
|
3109
|
+
);
|
|
3002
3110
|
return err(error);
|
|
3003
3111
|
}
|
|
3004
3112
|
return ok("run-ended");
|
|
@@ -3140,9 +3248,9 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
3140
3248
|
};
|
|
3141
3249
|
}
|
|
3142
3250
|
};
|
|
3143
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
3251
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, retryDelay, flowControl, debug) => {
|
|
3144
3252
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
3145
|
-
return ok("not-failure-callback");
|
|
3253
|
+
return ok({ result: "not-failure-callback" });
|
|
3146
3254
|
}
|
|
3147
3255
|
if (!failureFunction) {
|
|
3148
3256
|
return err(
|
|
@@ -3165,20 +3273,23 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3165
3273
|
if (!errorMessage) {
|
|
3166
3274
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3167
3275
|
}
|
|
3276
|
+
const userHeaders = recreateUserHeaders(request.headers);
|
|
3168
3277
|
const workflowContext = new WorkflowContext({
|
|
3169
3278
|
qstashClient,
|
|
3170
3279
|
workflowRunId,
|
|
3171
3280
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
3172
|
-
headers:
|
|
3281
|
+
headers: userHeaders,
|
|
3173
3282
|
steps: [],
|
|
3174
3283
|
url,
|
|
3175
3284
|
failureUrl: url,
|
|
3176
3285
|
debug,
|
|
3177
3286
|
env,
|
|
3178
3287
|
retries,
|
|
3288
|
+
retryDelay,
|
|
3179
3289
|
flowControl,
|
|
3180
|
-
telemetry: void 0
|
|
3290
|
+
telemetry: void 0,
|
|
3181
3291
|
// not going to make requests in authentication check
|
|
3292
|
+
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0
|
|
3182
3293
|
});
|
|
3183
3294
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3184
3295
|
routeFunction,
|
|
@@ -3190,16 +3301,16 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3190
3301
|
} else if (authCheck.value === "run-ended") {
|
|
3191
3302
|
return err(new WorkflowError("Not authorized to run the failure function."));
|
|
3192
3303
|
}
|
|
3193
|
-
await failureFunction({
|
|
3304
|
+
const failureResponse = await failureFunction({
|
|
3194
3305
|
context: workflowContext,
|
|
3195
3306
|
failStatus: status,
|
|
3196
3307
|
failResponse: errorMessage,
|
|
3197
3308
|
failHeaders: header
|
|
3198
3309
|
});
|
|
3310
|
+
return ok({ result: "is-failure-callback", response: failureResponse });
|
|
3199
3311
|
} catch (error) {
|
|
3200
3312
|
return err(error);
|
|
3201
3313
|
}
|
|
3202
|
-
return ok("is-failure-callback");
|
|
3203
3314
|
};
|
|
3204
3315
|
|
|
3205
3316
|
// src/serve/options.ts
|
|
@@ -3215,8 +3326,8 @@ var processOptions = (options) => {
|
|
|
3215
3326
|
baseUrl: environment.QSTASH_URL,
|
|
3216
3327
|
token: environment.QSTASH_TOKEN
|
|
3217
3328
|
}),
|
|
3218
|
-
onStepFinish: (workflowRunId,
|
|
3219
|
-
if (
|
|
3329
|
+
onStepFinish: (workflowRunId, _finishCondition, detailedFinishCondition) => {
|
|
3330
|
+
if (detailedFinishCondition?.condition === "auth-fail") {
|
|
3220
3331
|
console.error(AUTH_FAIL_MESSAGE);
|
|
3221
3332
|
return new Response(
|
|
3222
3333
|
JSON.stringify({
|
|
@@ -3224,19 +3335,33 @@ var processOptions = (options) => {
|
|
|
3224
3335
|
workflowRunId
|
|
3225
3336
|
}),
|
|
3226
3337
|
{
|
|
3227
|
-
status: 400
|
|
3338
|
+
status: 400,
|
|
3339
|
+
headers: {
|
|
3340
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3341
|
+
}
|
|
3228
3342
|
}
|
|
3229
3343
|
);
|
|
3230
|
-
} else if (
|
|
3231
|
-
return new Response(JSON.stringify(formatWorkflowError(
|
|
3344
|
+
} else if (detailedFinishCondition?.condition === "non-retryable-error") {
|
|
3345
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3232
3346
|
headers: {
|
|
3233
|
-
"Upstash-NonRetryable-Error": "true"
|
|
3347
|
+
"Upstash-NonRetryable-Error": "true",
|
|
3348
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3234
3349
|
},
|
|
3235
3350
|
status: 489
|
|
3236
3351
|
});
|
|
3352
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3353
|
+
return new Response(detailedFinishCondition.result ?? void 0, {
|
|
3354
|
+
status: 200,
|
|
3355
|
+
headers: {
|
|
3356
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3357
|
+
}
|
|
3358
|
+
});
|
|
3237
3359
|
}
|
|
3238
3360
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3239
|
-
status: 200
|
|
3361
|
+
status: 200,
|
|
3362
|
+
headers: {
|
|
3363
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3364
|
+
}
|
|
3240
3365
|
});
|
|
3241
3366
|
},
|
|
3242
3367
|
initialPayloadParser: (initialRequest) => {
|
|
@@ -3310,6 +3435,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3310
3435
|
baseUrl,
|
|
3311
3436
|
env,
|
|
3312
3437
|
retries,
|
|
3438
|
+
retryDelay,
|
|
3313
3439
|
useJSONContent,
|
|
3314
3440
|
disableTelemetry,
|
|
3315
3441
|
flowControl,
|
|
@@ -3340,10 +3466,14 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3340
3466
|
debug
|
|
3341
3467
|
);
|
|
3342
3468
|
if (workflowRunEnded) {
|
|
3343
|
-
return onStepFinish(workflowRunId, "workflow-already-ended"
|
|
3469
|
+
return onStepFinish(workflowRunId, "workflow-already-ended", {
|
|
3470
|
+
condition: "workflow-already-ended"
|
|
3471
|
+
});
|
|
3344
3472
|
}
|
|
3345
3473
|
if (isLastDuplicate) {
|
|
3346
|
-
return onStepFinish(workflowRunId, "duplicate-step"
|
|
3474
|
+
return onStepFinish(workflowRunId, "duplicate-step", {
|
|
3475
|
+
condition: "duplicate-step"
|
|
3476
|
+
});
|
|
3347
3477
|
}
|
|
3348
3478
|
const failureCheck = await handleFailure(
|
|
3349
3479
|
request,
|
|
@@ -3354,16 +3484,21 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3354
3484
|
failureFunction,
|
|
3355
3485
|
env,
|
|
3356
3486
|
retries,
|
|
3487
|
+
retryDelay,
|
|
3357
3488
|
flowControl,
|
|
3358
3489
|
debug
|
|
3359
3490
|
);
|
|
3360
3491
|
if (failureCheck.isErr()) {
|
|
3361
3492
|
throw failureCheck.error;
|
|
3362
|
-
} else if (failureCheck.value === "is-failure-callback") {
|
|
3493
|
+
} else if (failureCheck.value.result === "is-failure-callback") {
|
|
3363
3494
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
3364
|
-
return onStepFinish(workflowRunId, "failure-callback"
|
|
3495
|
+
return onStepFinish(workflowRunId, "failure-callback", {
|
|
3496
|
+
condition: "failure-callback",
|
|
3497
|
+
result: failureCheck.value.response
|
|
3498
|
+
});
|
|
3365
3499
|
}
|
|
3366
3500
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3501
|
+
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3367
3502
|
const workflowContext = new WorkflowContext({
|
|
3368
3503
|
qstashClient,
|
|
3369
3504
|
workflowRunId,
|
|
@@ -3375,9 +3510,11 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3375
3510
|
debug,
|
|
3376
3511
|
env,
|
|
3377
3512
|
retries,
|
|
3513
|
+
retryDelay,
|
|
3378
3514
|
telemetry,
|
|
3379
3515
|
invokeCount,
|
|
3380
|
-
flowControl
|
|
3516
|
+
flowControl,
|
|
3517
|
+
label
|
|
3381
3518
|
});
|
|
3382
3519
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3383
3520
|
routeFunction,
|
|
@@ -3390,7 +3527,8 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3390
3527
|
await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
|
|
3391
3528
|
return onStepFinish(
|
|
3392
3529
|
isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
|
|
3393
|
-
"auth-fail"
|
|
3530
|
+
"auth-fail",
|
|
3531
|
+
{ condition: "auth-fail" }
|
|
3394
3532
|
);
|
|
3395
3533
|
}
|
|
3396
3534
|
const callReturnCheck = await handleThirdPartyCallResult({
|
|
@@ -3400,6 +3538,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3400
3538
|
workflowUrl,
|
|
3401
3539
|
failureUrl: workflowFailureUrl,
|
|
3402
3540
|
retries,
|
|
3541
|
+
retryDelay,
|
|
3403
3542
|
flowControl,
|
|
3404
3543
|
telemetry,
|
|
3405
3544
|
debug
|
|
@@ -3427,19 +3566,28 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3427
3566
|
debug
|
|
3428
3567
|
});
|
|
3429
3568
|
if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
|
|
3430
|
-
return onStepFinish(workflowRunId, result.value
|
|
3569
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
3570
|
+
condition: "non-retryable-error",
|
|
3571
|
+
result: result.value
|
|
3572
|
+
});
|
|
3431
3573
|
}
|
|
3432
3574
|
if (result.isErr()) {
|
|
3433
3575
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3434
3576
|
throw result.error;
|
|
3435
3577
|
}
|
|
3436
3578
|
await debug?.log("INFO", "RESPONSE_WORKFLOW");
|
|
3437
|
-
return onStepFinish(workflowContext.workflowRunId, "success"
|
|
3579
|
+
return onStepFinish(workflowContext.workflowRunId, "success", {
|
|
3580
|
+
condition: "success"
|
|
3581
|
+
});
|
|
3438
3582
|
} else if (callReturnCheck.value === "workflow-ended") {
|
|
3439
|
-
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended"
|
|
3583
|
+
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended", {
|
|
3584
|
+
condition: "workflow-already-ended"
|
|
3585
|
+
});
|
|
3440
3586
|
}
|
|
3441
3587
|
await debug?.log("INFO", "RESPONSE_DEFAULT");
|
|
3442
|
-
return onStepFinish("no-workflow-id", "fromCallback"
|
|
3588
|
+
return onStepFinish("no-workflow-id", "fromCallback", {
|
|
3589
|
+
condition: "fromCallback"
|
|
3590
|
+
});
|
|
3443
3591
|
};
|
|
3444
3592
|
const safeHandler = async (request) => {
|
|
3445
3593
|
try {
|
|
@@ -3454,11 +3602,17 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3454
3602
|
Original error: '${formattedError.message}'`;
|
|
3455
3603
|
console.error(errorMessage);
|
|
3456
3604
|
return new Response(errorMessage, {
|
|
3457
|
-
status: 500
|
|
3605
|
+
status: 500,
|
|
3606
|
+
headers: {
|
|
3607
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3608
|
+
}
|
|
3458
3609
|
});
|
|
3459
3610
|
}
|
|
3460
3611
|
return new Response(JSON.stringify(formattedError), {
|
|
3461
|
-
status: 500
|
|
3612
|
+
status: 500,
|
|
3613
|
+
headers: {
|
|
3614
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3615
|
+
}
|
|
3462
3616
|
});
|
|
3463
3617
|
}
|
|
3464
3618
|
};
|
|
@@ -3533,6 +3687,20 @@ var DLQ = class _DLQ {
|
|
|
3533
3687
|
}
|
|
3534
3688
|
return workflowRuns[0];
|
|
3535
3689
|
}
|
|
3690
|
+
/**
|
|
3691
|
+
* Retry the failure callback of a workflow run whose failureUrl/failureFunction
|
|
3692
|
+
* request has failed.
|
|
3693
|
+
*
|
|
3694
|
+
* @param dlqId - The ID of the DLQ message to retry.
|
|
3695
|
+
* @returns
|
|
3696
|
+
*/
|
|
3697
|
+
async retryFailureFunction({ dlqId }) {
|
|
3698
|
+
const response = await this.client.http.request({
|
|
3699
|
+
path: ["v2", "workflows", "dlq", "callback", dlqId],
|
|
3700
|
+
method: "POST"
|
|
3701
|
+
});
|
|
3702
|
+
return response;
|
|
3703
|
+
}
|
|
3536
3704
|
static handleDLQOptions(options) {
|
|
3537
3705
|
const { dlqId, flowControl, retries } = options;
|
|
3538
3706
|
const headers = {};
|
|
@@ -3691,16 +3859,21 @@ var Client4 = class {
|
|
|
3691
3859
|
const finalWorkflowRunId = getWorkflowRunId(option.workflowRunId);
|
|
3692
3860
|
const context = new WorkflowContext({
|
|
3693
3861
|
qstashClient: this.client,
|
|
3694
|
-
// @ts-expect-error
|
|
3695
|
-
headers: new Headers(
|
|
3862
|
+
// @ts-expect-error header type mismatch because of bun
|
|
3863
|
+
headers: new Headers({
|
|
3864
|
+
...option.headers ?? {},
|
|
3865
|
+
...option.label ? { [WORKFLOW_LABEL_HEADER]: option.label } : {}
|
|
3866
|
+
}),
|
|
3696
3867
|
initialPayload: option.body,
|
|
3697
3868
|
steps: [],
|
|
3698
3869
|
url: option.url,
|
|
3699
3870
|
workflowRunId: finalWorkflowRunId,
|
|
3700
3871
|
retries: option.retries,
|
|
3872
|
+
retryDelay: option.retryDelay,
|
|
3701
3873
|
telemetry: { sdk: SDK_TELEMETRY },
|
|
3702
3874
|
flowControl: option.flowControl,
|
|
3703
|
-
failureUrl
|
|
3875
|
+
failureUrl,
|
|
3876
|
+
label: option.label
|
|
3704
3877
|
});
|
|
3705
3878
|
return {
|
|
3706
3879
|
workflowContext: context,
|
|
@@ -3766,6 +3939,9 @@ var Client4 = class {
|
|
|
3766
3939
|
if (workflowCreatedAt) {
|
|
3767
3940
|
urlParams.append("workflowCreatedAt", workflowCreatedAt.toString());
|
|
3768
3941
|
}
|
|
3942
|
+
if (params?.label) {
|
|
3943
|
+
urlParams.append("label", params.label);
|
|
3944
|
+
}
|
|
3769
3945
|
const result = await this.client.http.request({
|
|
3770
3946
|
path: ["v2", "workflows", `events?${urlParams.toString()}`]
|
|
3771
3947
|
});
|