@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/astro.mjs
CHANGED
|
@@ -37,12 +37,13 @@ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
|
37
37
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
38
38
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
39
39
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
40
|
+
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
40
41
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
41
42
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
42
43
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
43
44
|
var NO_CONCURRENCY = 1;
|
|
44
45
|
var DEFAULT_RETRIES = 3;
|
|
45
|
-
var VERSION = "v0.2.
|
|
46
|
+
var VERSION = "v0.2.18";
|
|
46
47
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
47
48
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
48
49
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -144,6 +145,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
144
145
|
body,
|
|
145
146
|
timeout: agentCallParams?.timeout,
|
|
146
147
|
retries: agentCallParams?.retries,
|
|
148
|
+
retryDelay: agentCallParams?.retryDelay,
|
|
147
149
|
flowControl: agentCallParams?.flowControl
|
|
148
150
|
});
|
|
149
151
|
const responseHeaders = new Headers(
|
|
@@ -287,7 +289,10 @@ var serveManyBase = ({
|
|
|
287
289
|
return new Response(
|
|
288
290
|
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
289
291
|
{
|
|
290
|
-
status: 404
|
|
292
|
+
status: 404,
|
|
293
|
+
headers: {
|
|
294
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
295
|
+
}
|
|
291
296
|
}
|
|
292
297
|
);
|
|
293
298
|
}
|
|
@@ -296,7 +301,10 @@ var serveManyBase = ({
|
|
|
296
301
|
return new Response(
|
|
297
302
|
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
298
303
|
{
|
|
299
|
-
status: 404
|
|
304
|
+
status: 404,
|
|
305
|
+
headers: {
|
|
306
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
307
|
+
}
|
|
300
308
|
}
|
|
301
309
|
);
|
|
302
310
|
}
|
|
@@ -831,6 +839,7 @@ var triggerFirstInvocation = async (params) => {
|
|
|
831
839
|
workflowUrl: workflowContext.url,
|
|
832
840
|
failureUrl: workflowContext.failureUrl,
|
|
833
841
|
retries: workflowContext.retries,
|
|
842
|
+
retryDelay: workflowContext.retryDelay,
|
|
834
843
|
telemetry,
|
|
835
844
|
flowControl: workflowContext.flowControl,
|
|
836
845
|
useJSONContent: useJSONContent ?? false
|
|
@@ -844,6 +853,9 @@ var triggerFirstInvocation = async (params) => {
|
|
|
844
853
|
if (useJSONContent) {
|
|
845
854
|
headers["content-type"] = "application/json";
|
|
846
855
|
}
|
|
856
|
+
if (workflowContext.label) {
|
|
857
|
+
headers[WORKFLOW_LABEL_HEADER] = workflowContext.label;
|
|
858
|
+
}
|
|
847
859
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
848
860
|
return {
|
|
849
861
|
headers,
|
|
@@ -944,10 +956,11 @@ var recreateUserHeaders = (headers) => {
|
|
|
944
956
|
const pairs = headers.entries();
|
|
945
957
|
for (const [header, value] of pairs) {
|
|
946
958
|
const headerLowerCase = header.toLowerCase();
|
|
947
|
-
|
|
959
|
+
const isUserHeader = !headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
948
960
|
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
949
961
|
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
950
|
-
headerLowerCase !== "render-proxy-ttl")
|
|
962
|
+
headerLowerCase !== "render-proxy-ttl" || headerLowerCase === WORKFLOW_LABEL_HEADER.toLocaleLowerCase();
|
|
963
|
+
if (isUserHeader) {
|
|
951
964
|
filteredHeaders.append(header, value);
|
|
952
965
|
}
|
|
953
966
|
}
|
|
@@ -960,6 +973,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
960
973
|
workflowUrl,
|
|
961
974
|
failureUrl,
|
|
962
975
|
retries,
|
|
976
|
+
retryDelay,
|
|
963
977
|
telemetry,
|
|
964
978
|
flowControl,
|
|
965
979
|
debug
|
|
@@ -1030,6 +1044,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
1030
1044
|
workflowUrl,
|
|
1031
1045
|
failureUrl,
|
|
1032
1046
|
retries,
|
|
1047
|
+
retryDelay,
|
|
1033
1048
|
telemetry,
|
|
1034
1049
|
flowControl
|
|
1035
1050
|
},
|
|
@@ -1180,7 +1195,8 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1180
1195
|
workflowRunId: context.workflowRunId,
|
|
1181
1196
|
workflowUrl: context.url,
|
|
1182
1197
|
failureUrl: context.failureUrl,
|
|
1183
|
-
retries: context.retries,
|
|
1198
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1199
|
+
retryDelay: context.retryDelay,
|
|
1184
1200
|
useJSONContent: false,
|
|
1185
1201
|
telemetry,
|
|
1186
1202
|
flowControl: context.flowControl
|
|
@@ -1199,6 +1215,9 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1199
1215
|
body,
|
|
1200
1216
|
headers,
|
|
1201
1217
|
method: "POST",
|
|
1218
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1219
|
+
retryDelay: context.retryDelay,
|
|
1220
|
+
flowControl: context.flowControl,
|
|
1202
1221
|
url: context.url
|
|
1203
1222
|
}
|
|
1204
1223
|
]);
|
|
@@ -1269,6 +1288,9 @@ var LazySleepStep = class extends BaseLazyStep {
|
|
|
1269
1288
|
headers,
|
|
1270
1289
|
method: "POST",
|
|
1271
1290
|
url: context.url,
|
|
1291
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1292
|
+
retryDelay: context.retryDelay,
|
|
1293
|
+
flowControl: context.flowControl,
|
|
1272
1294
|
delay: isParallel ? void 0 : this.sleep
|
|
1273
1295
|
}
|
|
1274
1296
|
]);
|
|
@@ -1311,6 +1333,9 @@ var LazySleepUntilStep = class extends BaseLazyStep {
|
|
|
1311
1333
|
headers,
|
|
1312
1334
|
method: "POST",
|
|
1313
1335
|
url: context.url,
|
|
1336
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1337
|
+
retryDelay: context.retryDelay,
|
|
1338
|
+
flowControl: context.flowControl,
|
|
1314
1339
|
notBefore: isParallel ? void 0 : this.sleepUntil
|
|
1315
1340
|
}
|
|
1316
1341
|
]);
|
|
@@ -1322,17 +1347,19 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1322
1347
|
body;
|
|
1323
1348
|
headers;
|
|
1324
1349
|
retries;
|
|
1350
|
+
retryDelay;
|
|
1325
1351
|
timeout;
|
|
1326
1352
|
flowControl;
|
|
1327
1353
|
stepType = "Call";
|
|
1328
1354
|
allowUndefinedOut = false;
|
|
1329
|
-
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
1355
|
+
constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl) {
|
|
1330
1356
|
super(stepName);
|
|
1331
1357
|
this.url = url;
|
|
1332
1358
|
this.method = method;
|
|
1333
1359
|
this.body = body;
|
|
1334
1360
|
this.headers = headers;
|
|
1335
1361
|
this.retries = retries;
|
|
1362
|
+
this.retryDelay = retryDelay;
|
|
1336
1363
|
this.timeout = timeout;
|
|
1337
1364
|
this.flowControl = flowControl;
|
|
1338
1365
|
}
|
|
@@ -1407,6 +1434,9 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1407
1434
|
getHeaders({ context, telemetry, invokeCount, step }) {
|
|
1408
1435
|
const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
|
|
1409
1436
|
headers["Upstash-Retries"] = this.retries.toString();
|
|
1437
|
+
if (this.retryDelay) {
|
|
1438
|
+
headers["Upstash-Retry-Delay"] = this.retryDelay;
|
|
1439
|
+
}
|
|
1410
1440
|
headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
1411
1441
|
if (this.flowControl) {
|
|
1412
1442
|
const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
|
|
@@ -1428,7 +1458,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1428
1458
|
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1429
1459
|
"Upstash-Callback-Workflow-Init": "false",
|
|
1430
1460
|
"Upstash-Callback-Workflow-Url": context.url,
|
|
1431
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1461
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1432
1462
|
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1433
1463
|
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1434
1464
|
"Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
|
|
@@ -1446,7 +1476,10 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1446
1476
|
headers,
|
|
1447
1477
|
body: JSON.stringify(this.body),
|
|
1448
1478
|
method: this.method,
|
|
1449
|
-
url: this.url
|
|
1479
|
+
url: this.url,
|
|
1480
|
+
retries: DEFAULT_RETRIES === this.retries ? void 0 : this.retries,
|
|
1481
|
+
retryDelay: this.retryDelay,
|
|
1482
|
+
flowControl: this.flowControl
|
|
1450
1483
|
}
|
|
1451
1484
|
]);
|
|
1452
1485
|
}
|
|
@@ -1575,6 +1608,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1575
1608
|
headers = {},
|
|
1576
1609
|
workflowRunId,
|
|
1577
1610
|
retries,
|
|
1611
|
+
retryDelay,
|
|
1578
1612
|
flowControl
|
|
1579
1613
|
}) {
|
|
1580
1614
|
super(stepName);
|
|
@@ -1584,6 +1618,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1584
1618
|
headers,
|
|
1585
1619
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1586
1620
|
retries,
|
|
1621
|
+
retryDelay,
|
|
1587
1622
|
flowControl
|
|
1588
1623
|
};
|
|
1589
1624
|
const { workflowId } = workflow;
|
|
@@ -1628,6 +1663,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1628
1663
|
workflowUrl: context.url,
|
|
1629
1664
|
failureUrl: context.failureUrl,
|
|
1630
1665
|
retries: context.retries,
|
|
1666
|
+
retryDelay: context.retryDelay,
|
|
1631
1667
|
telemetry,
|
|
1632
1668
|
flowControl: context.flowControl,
|
|
1633
1669
|
useJSONContent: false
|
|
@@ -1653,11 +1689,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1653
1689
|
headers = {},
|
|
1654
1690
|
workflowRunId = getWorkflowRunId(),
|
|
1655
1691
|
retries,
|
|
1692
|
+
retryDelay,
|
|
1656
1693
|
flowControl
|
|
1657
1694
|
} = this.params;
|
|
1658
1695
|
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1659
1696
|
const {
|
|
1660
1697
|
retries: workflowRetries,
|
|
1698
|
+
retryDelay: workflowRetryDelay,
|
|
1661
1699
|
failureFunction,
|
|
1662
1700
|
failureUrl,
|
|
1663
1701
|
useJSONContent,
|
|
@@ -1669,6 +1707,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1669
1707
|
workflowRunId,
|
|
1670
1708
|
workflowUrl: newUrl,
|
|
1671
1709
|
retries: retries ?? workflowRetries,
|
|
1710
|
+
retryDelay: retryDelay ?? workflowRetryDelay,
|
|
1672
1711
|
telemetry,
|
|
1673
1712
|
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1674
1713
|
flowControl: flowControl ?? workflowFlowControl,
|
|
@@ -1721,6 +1760,7 @@ var WorkflowHeaders = class {
|
|
|
1721
1760
|
getHeaders() {
|
|
1722
1761
|
this.addBaseHeaders();
|
|
1723
1762
|
this.addRetries();
|
|
1763
|
+
this.addRetryDelay();
|
|
1724
1764
|
this.addFlowControl();
|
|
1725
1765
|
this.addUserHeaders();
|
|
1726
1766
|
this.addInvokeCount();
|
|
@@ -1734,7 +1774,7 @@ var WorkflowHeaders = class {
|
|
|
1734
1774
|
[WORKFLOW_INIT_HEADER]: this.initHeaderValue,
|
|
1735
1775
|
[WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
|
|
1736
1776
|
[WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
|
|
1737
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1777
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1738
1778
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1739
1779
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
|
|
1740
1780
|
...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
|
|
@@ -1766,6 +1806,16 @@ var WorkflowHeaders = class {
|
|
|
1766
1806
|
this.headers.failureHeaders["Retries"] = retries;
|
|
1767
1807
|
}
|
|
1768
1808
|
}
|
|
1809
|
+
addRetryDelay() {
|
|
1810
|
+
if (this.workflowConfig.retryDelay === void 0 || this.workflowConfig.retryDelay === "") {
|
|
1811
|
+
return;
|
|
1812
|
+
}
|
|
1813
|
+
const retryDelay = this.workflowConfig.retryDelay.toString();
|
|
1814
|
+
this.headers.workflowHeaders["Retry-Delay"] = retryDelay;
|
|
1815
|
+
if (this.workflowConfig.failureUrl) {
|
|
1816
|
+
this.headers.failureHeaders["Retry-Delay"] = retryDelay;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1769
1819
|
addFlowControl() {
|
|
1770
1820
|
if (!this.workflowConfig.flowControl) {
|
|
1771
1821
|
return;
|
|
@@ -1800,10 +1850,13 @@ var WorkflowHeaders = class {
|
|
|
1800
1850
|
this.headers.failureHeaders["Workflow-Init"] = "false";
|
|
1801
1851
|
this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
|
|
1802
1852
|
this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
|
|
1803
|
-
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
|
|
1853
|
+
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody,WF_DetectTrigger";
|
|
1804
1854
|
if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
|
|
1805
1855
|
this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
|
|
1806
1856
|
}
|
|
1857
|
+
if (this.workflowConfig.retryDelay !== void 0 && this.workflowConfig.retryDelay !== "") {
|
|
1858
|
+
this.headers.failureHeaders["Retry-Delay"] = this.workflowConfig.retryDelay.toString();
|
|
1859
|
+
}
|
|
1807
1860
|
}
|
|
1808
1861
|
addContentType() {
|
|
1809
1862
|
if (this.workflowConfig.useJSONContent) {
|
|
@@ -1885,6 +1938,7 @@ var submitParallelSteps = async ({
|
|
|
1885
1938
|
workflowUrl: context.url,
|
|
1886
1939
|
failureUrl: context.failureUrl,
|
|
1887
1940
|
retries: context.retries,
|
|
1941
|
+
retryDelay: context.retryDelay,
|
|
1888
1942
|
flowControl: context.flowControl,
|
|
1889
1943
|
telemetry
|
|
1890
1944
|
},
|
|
@@ -2305,7 +2359,7 @@ var BaseWorkflowApi = class {
|
|
|
2305
2359
|
*/
|
|
2306
2360
|
async callApi(stepName, settings) {
|
|
2307
2361
|
const { url, appendHeaders, method } = getProviderInfo(settings.api);
|
|
2308
|
-
const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
|
|
2362
|
+
const { method: userMethod, body, headers = {}, retries = 0, retryDelay, timeout } = settings;
|
|
2309
2363
|
return await this.context.call(stepName, {
|
|
2310
2364
|
url,
|
|
2311
2365
|
method: userMethod ?? method,
|
|
@@ -2315,6 +2369,7 @@ var BaseWorkflowApi = class {
|
|
|
2315
2369
|
...headers
|
|
2316
2370
|
},
|
|
2317
2371
|
retries,
|
|
2372
|
+
retryDelay,
|
|
2318
2373
|
timeout
|
|
2319
2374
|
});
|
|
2320
2375
|
}
|
|
@@ -2726,11 +2781,58 @@ var WorkflowContext = class {
|
|
|
2726
2781
|
* Number of retries
|
|
2727
2782
|
*/
|
|
2728
2783
|
retries;
|
|
2784
|
+
/**
|
|
2785
|
+
* Delay between retries.
|
|
2786
|
+
*
|
|
2787
|
+
* By default, the `retryDelay` is exponential backoff.
|
|
2788
|
+
* More details can be found in: https://upstash.com/docs/qstash/features/retry.
|
|
2789
|
+
*
|
|
2790
|
+
* The `retryDelay` option allows you to customize the delay (in milliseconds) between retry attempts when message delivery fails.
|
|
2791
|
+
*
|
|
2792
|
+
* You can use mathematical expressions and the following built-in functions to calculate the delay dynamically.
|
|
2793
|
+
* The special variable `retried` represents the current retry attempt count (starting from 0).
|
|
2794
|
+
*
|
|
2795
|
+
* Supported functions:
|
|
2796
|
+
* - `pow`
|
|
2797
|
+
* - `sqrt`
|
|
2798
|
+
* - `abs`
|
|
2799
|
+
* - `exp`
|
|
2800
|
+
* - `floor`
|
|
2801
|
+
* - `ceil`
|
|
2802
|
+
* - `round`
|
|
2803
|
+
* - `min`
|
|
2804
|
+
* - `max`
|
|
2805
|
+
*
|
|
2806
|
+
* Examples of valid `retryDelay` values:
|
|
2807
|
+
* ```ts
|
|
2808
|
+
* 1000 // 1 second
|
|
2809
|
+
* 1000 * (1 + retried) // 1 second multiplied by the current retry attempt
|
|
2810
|
+
* pow(2, retried) // 2 to the power of the current retry attempt
|
|
2811
|
+
* max(10, pow(2, retried)) // The greater of 10 or 2^retried
|
|
2812
|
+
* ```
|
|
2813
|
+
*/
|
|
2814
|
+
retryDelay;
|
|
2729
2815
|
/**
|
|
2730
2816
|
* Settings for controlling the number of active requests
|
|
2731
2817
|
* and number of requests per second with the same key.
|
|
2732
2818
|
*/
|
|
2733
2819
|
flowControl;
|
|
2820
|
+
/**
|
|
2821
|
+
* Label to apply to the workflow run.
|
|
2822
|
+
*
|
|
2823
|
+
* Can be used to filter the workflow run logs.
|
|
2824
|
+
*
|
|
2825
|
+
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2826
|
+
* with `client.trigger`:
|
|
2827
|
+
*
|
|
2828
|
+
* ```ts
|
|
2829
|
+
* await client.trigger({
|
|
2830
|
+
* url: "https://workflow-endpoint.com",
|
|
2831
|
+
* label: "my-label"
|
|
2832
|
+
* });
|
|
2833
|
+
* ```
|
|
2834
|
+
*/
|
|
2835
|
+
label;
|
|
2734
2836
|
constructor({
|
|
2735
2837
|
qstashClient,
|
|
2736
2838
|
workflowRunId,
|
|
@@ -2742,9 +2844,11 @@ var WorkflowContext = class {
|
|
|
2742
2844
|
initialPayload,
|
|
2743
2845
|
env,
|
|
2744
2846
|
retries,
|
|
2847
|
+
retryDelay,
|
|
2745
2848
|
telemetry,
|
|
2746
2849
|
invokeCount,
|
|
2747
|
-
flowControl
|
|
2850
|
+
flowControl,
|
|
2851
|
+
label
|
|
2748
2852
|
}) {
|
|
2749
2853
|
this.qstashClient = qstashClient;
|
|
2750
2854
|
this.workflowRunId = workflowRunId;
|
|
@@ -2755,7 +2859,9 @@ var WorkflowContext = class {
|
|
|
2755
2859
|
this.requestPayload = initialPayload;
|
|
2756
2860
|
this.env = env ?? {};
|
|
2757
2861
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2862
|
+
this.retryDelay = retryDelay;
|
|
2758
2863
|
this.flowControl = flowControl;
|
|
2864
|
+
this.label = label;
|
|
2759
2865
|
this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
|
|
2760
2866
|
}
|
|
2761
2867
|
/**
|
|
@@ -2836,6 +2942,7 @@ var WorkflowContext = class {
|
|
|
2836
2942
|
settings.body,
|
|
2837
2943
|
settings.headers || {},
|
|
2838
2944
|
settings.retries || 0,
|
|
2945
|
+
settings.retryDelay,
|
|
2839
2946
|
settings.timeout,
|
|
2840
2947
|
settings.flowControl ?? settings.workflow.options.flowControl
|
|
2841
2948
|
);
|
|
@@ -2846,6 +2953,7 @@ var WorkflowContext = class {
|
|
|
2846
2953
|
body,
|
|
2847
2954
|
headers = {},
|
|
2848
2955
|
retries = 0,
|
|
2956
|
+
retryDelay,
|
|
2849
2957
|
timeout,
|
|
2850
2958
|
flowControl
|
|
2851
2959
|
} = settings;
|
|
@@ -2856,6 +2964,7 @@ var WorkflowContext = class {
|
|
|
2856
2964
|
body,
|
|
2857
2965
|
headers,
|
|
2858
2966
|
retries,
|
|
2967
|
+
retryDelay,
|
|
2859
2968
|
timeout,
|
|
2860
2969
|
flowControl
|
|
2861
2970
|
);
|
|
@@ -2866,7 +2975,7 @@ var WorkflowContext = class {
|
|
|
2866
2975
|
* Pauses workflow execution until a specific event occurs or a timeout is reached.
|
|
2867
2976
|
*
|
|
2868
2977
|
*```ts
|
|
2869
|
-
* const result = await workflow.waitForEvent("payment-confirmed", {
|
|
2978
|
+
* const result = await workflow.waitForEvent("payment-confirmed", "payment.confirmed", {
|
|
2870
2979
|
* timeout: "5m"
|
|
2871
2980
|
* });
|
|
2872
2981
|
*```
|
|
@@ -2892,7 +3001,7 @@ var WorkflowContext = class {
|
|
|
2892
3001
|
* @param stepName
|
|
2893
3002
|
* @param eventId - Unique identifier for the event to wait for
|
|
2894
3003
|
* @param options - Configuration options.
|
|
2895
|
-
* @returns `{ timeout: boolean, eventData:
|
|
3004
|
+
* @returns `{ timeout: boolean, eventData: TEventData }`.
|
|
2896
3005
|
* The `timeout` property specifies if the workflow has timed out. The `eventData`
|
|
2897
3006
|
* is the data passed when notifying this workflow of an event.
|
|
2898
3007
|
*/
|
|
@@ -3052,7 +3161,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3052
3161
|
initialPayload: context.requestPayload,
|
|
3053
3162
|
env: context.env,
|
|
3054
3163
|
retries: context.retries,
|
|
3055
|
-
|
|
3164
|
+
retryDelay: context.retryDelay,
|
|
3165
|
+
flowControl: context.flowControl,
|
|
3166
|
+
label: context.label
|
|
3056
3167
|
});
|
|
3057
3168
|
try {
|
|
3058
3169
|
await routeFunction(disabledContext);
|
|
@@ -3060,6 +3171,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3060
3171
|
if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
|
|
3061
3172
|
return ok("step-found");
|
|
3062
3173
|
}
|
|
3174
|
+
console.warn(
|
|
3175
|
+
"Upstash Workflow: Received an error while authorizing request. Please avoid throwing errors before the first step of your workflow."
|
|
3176
|
+
);
|
|
3063
3177
|
return err(error);
|
|
3064
3178
|
}
|
|
3065
3179
|
return ok("run-ended");
|
|
@@ -3201,9 +3315,9 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
3201
3315
|
};
|
|
3202
3316
|
}
|
|
3203
3317
|
};
|
|
3204
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
3318
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, retryDelay, flowControl, debug) => {
|
|
3205
3319
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
3206
|
-
return ok("not-failure-callback");
|
|
3320
|
+
return ok({ result: "not-failure-callback" });
|
|
3207
3321
|
}
|
|
3208
3322
|
if (!failureFunction) {
|
|
3209
3323
|
return err(
|
|
@@ -3226,20 +3340,23 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3226
3340
|
if (!errorMessage) {
|
|
3227
3341
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3228
3342
|
}
|
|
3343
|
+
const userHeaders = recreateUserHeaders(request.headers);
|
|
3229
3344
|
const workflowContext = new WorkflowContext({
|
|
3230
3345
|
qstashClient,
|
|
3231
3346
|
workflowRunId,
|
|
3232
3347
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
3233
|
-
headers:
|
|
3348
|
+
headers: userHeaders,
|
|
3234
3349
|
steps: [],
|
|
3235
3350
|
url,
|
|
3236
3351
|
failureUrl: url,
|
|
3237
3352
|
debug,
|
|
3238
3353
|
env,
|
|
3239
3354
|
retries,
|
|
3355
|
+
retryDelay,
|
|
3240
3356
|
flowControl,
|
|
3241
|
-
telemetry: void 0
|
|
3357
|
+
telemetry: void 0,
|
|
3242
3358
|
// not going to make requests in authentication check
|
|
3359
|
+
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0
|
|
3243
3360
|
});
|
|
3244
3361
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3245
3362
|
routeFunction,
|
|
@@ -3251,16 +3368,16 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3251
3368
|
} else if (authCheck.value === "run-ended") {
|
|
3252
3369
|
return err(new WorkflowError("Not authorized to run the failure function."));
|
|
3253
3370
|
}
|
|
3254
|
-
await failureFunction({
|
|
3371
|
+
const failureResponse = await failureFunction({
|
|
3255
3372
|
context: workflowContext,
|
|
3256
3373
|
failStatus: status,
|
|
3257
3374
|
failResponse: errorMessage,
|
|
3258
3375
|
failHeaders: header
|
|
3259
3376
|
});
|
|
3377
|
+
return ok({ result: "is-failure-callback", response: failureResponse });
|
|
3260
3378
|
} catch (error) {
|
|
3261
3379
|
return err(error);
|
|
3262
3380
|
}
|
|
3263
|
-
return ok("is-failure-callback");
|
|
3264
3381
|
};
|
|
3265
3382
|
|
|
3266
3383
|
// src/serve/options.ts
|
|
@@ -3276,8 +3393,8 @@ var processOptions = (options) => {
|
|
|
3276
3393
|
baseUrl: environment.QSTASH_URL,
|
|
3277
3394
|
token: environment.QSTASH_TOKEN
|
|
3278
3395
|
}),
|
|
3279
|
-
onStepFinish: (workflowRunId,
|
|
3280
|
-
if (
|
|
3396
|
+
onStepFinish: (workflowRunId, _finishCondition, detailedFinishCondition) => {
|
|
3397
|
+
if (detailedFinishCondition?.condition === "auth-fail") {
|
|
3281
3398
|
console.error(AUTH_FAIL_MESSAGE);
|
|
3282
3399
|
return new Response(
|
|
3283
3400
|
JSON.stringify({
|
|
@@ -3285,19 +3402,33 @@ var processOptions = (options) => {
|
|
|
3285
3402
|
workflowRunId
|
|
3286
3403
|
}),
|
|
3287
3404
|
{
|
|
3288
|
-
status: 400
|
|
3405
|
+
status: 400,
|
|
3406
|
+
headers: {
|
|
3407
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3408
|
+
}
|
|
3289
3409
|
}
|
|
3290
3410
|
);
|
|
3291
|
-
} else if (
|
|
3292
|
-
return new Response(JSON.stringify(formatWorkflowError(
|
|
3411
|
+
} else if (detailedFinishCondition?.condition === "non-retryable-error") {
|
|
3412
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3293
3413
|
headers: {
|
|
3294
|
-
"Upstash-NonRetryable-Error": "true"
|
|
3414
|
+
"Upstash-NonRetryable-Error": "true",
|
|
3415
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3295
3416
|
},
|
|
3296
3417
|
status: 489
|
|
3297
3418
|
});
|
|
3419
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3420
|
+
return new Response(detailedFinishCondition.result ?? void 0, {
|
|
3421
|
+
status: 200,
|
|
3422
|
+
headers: {
|
|
3423
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3424
|
+
}
|
|
3425
|
+
});
|
|
3298
3426
|
}
|
|
3299
3427
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3300
|
-
status: 200
|
|
3428
|
+
status: 200,
|
|
3429
|
+
headers: {
|
|
3430
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3431
|
+
}
|
|
3301
3432
|
});
|
|
3302
3433
|
},
|
|
3303
3434
|
initialPayloadParser: (initialRequest) => {
|
|
@@ -3371,6 +3502,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3371
3502
|
baseUrl,
|
|
3372
3503
|
env,
|
|
3373
3504
|
retries,
|
|
3505
|
+
retryDelay,
|
|
3374
3506
|
useJSONContent,
|
|
3375
3507
|
disableTelemetry,
|
|
3376
3508
|
flowControl,
|
|
@@ -3401,10 +3533,14 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3401
3533
|
debug
|
|
3402
3534
|
);
|
|
3403
3535
|
if (workflowRunEnded) {
|
|
3404
|
-
return onStepFinish(workflowRunId, "workflow-already-ended"
|
|
3536
|
+
return onStepFinish(workflowRunId, "workflow-already-ended", {
|
|
3537
|
+
condition: "workflow-already-ended"
|
|
3538
|
+
});
|
|
3405
3539
|
}
|
|
3406
3540
|
if (isLastDuplicate) {
|
|
3407
|
-
return onStepFinish(workflowRunId, "duplicate-step"
|
|
3541
|
+
return onStepFinish(workflowRunId, "duplicate-step", {
|
|
3542
|
+
condition: "duplicate-step"
|
|
3543
|
+
});
|
|
3408
3544
|
}
|
|
3409
3545
|
const failureCheck = await handleFailure(
|
|
3410
3546
|
request,
|
|
@@ -3415,16 +3551,21 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3415
3551
|
failureFunction,
|
|
3416
3552
|
env,
|
|
3417
3553
|
retries,
|
|
3554
|
+
retryDelay,
|
|
3418
3555
|
flowControl,
|
|
3419
3556
|
debug
|
|
3420
3557
|
);
|
|
3421
3558
|
if (failureCheck.isErr()) {
|
|
3422
3559
|
throw failureCheck.error;
|
|
3423
|
-
} else if (failureCheck.value === "is-failure-callback") {
|
|
3560
|
+
} else if (failureCheck.value.result === "is-failure-callback") {
|
|
3424
3561
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
3425
|
-
return onStepFinish(workflowRunId, "failure-callback"
|
|
3562
|
+
return onStepFinish(workflowRunId, "failure-callback", {
|
|
3563
|
+
condition: "failure-callback",
|
|
3564
|
+
result: failureCheck.value.response
|
|
3565
|
+
});
|
|
3426
3566
|
}
|
|
3427
3567
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3568
|
+
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3428
3569
|
const workflowContext = new WorkflowContext({
|
|
3429
3570
|
qstashClient,
|
|
3430
3571
|
workflowRunId,
|
|
@@ -3436,9 +3577,11 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3436
3577
|
debug,
|
|
3437
3578
|
env,
|
|
3438
3579
|
retries,
|
|
3580
|
+
retryDelay,
|
|
3439
3581
|
telemetry,
|
|
3440
3582
|
invokeCount,
|
|
3441
|
-
flowControl
|
|
3583
|
+
flowControl,
|
|
3584
|
+
label
|
|
3442
3585
|
});
|
|
3443
3586
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3444
3587
|
routeFunction,
|
|
@@ -3451,7 +3594,8 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3451
3594
|
await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
|
|
3452
3595
|
return onStepFinish(
|
|
3453
3596
|
isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
|
|
3454
|
-
"auth-fail"
|
|
3597
|
+
"auth-fail",
|
|
3598
|
+
{ condition: "auth-fail" }
|
|
3455
3599
|
);
|
|
3456
3600
|
}
|
|
3457
3601
|
const callReturnCheck = await handleThirdPartyCallResult({
|
|
@@ -3461,6 +3605,7 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3461
3605
|
workflowUrl,
|
|
3462
3606
|
failureUrl: workflowFailureUrl,
|
|
3463
3607
|
retries,
|
|
3608
|
+
retryDelay,
|
|
3464
3609
|
flowControl,
|
|
3465
3610
|
telemetry,
|
|
3466
3611
|
debug
|
|
@@ -3488,19 +3633,28 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3488
3633
|
debug
|
|
3489
3634
|
});
|
|
3490
3635
|
if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
|
|
3491
|
-
return onStepFinish(workflowRunId, result.value
|
|
3636
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
3637
|
+
condition: "non-retryable-error",
|
|
3638
|
+
result: result.value
|
|
3639
|
+
});
|
|
3492
3640
|
}
|
|
3493
3641
|
if (result.isErr()) {
|
|
3494
3642
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3495
3643
|
throw result.error;
|
|
3496
3644
|
}
|
|
3497
3645
|
await debug?.log("INFO", "RESPONSE_WORKFLOW");
|
|
3498
|
-
return onStepFinish(workflowContext.workflowRunId, "success"
|
|
3646
|
+
return onStepFinish(workflowContext.workflowRunId, "success", {
|
|
3647
|
+
condition: "success"
|
|
3648
|
+
});
|
|
3499
3649
|
} else if (callReturnCheck.value === "workflow-ended") {
|
|
3500
|
-
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended"
|
|
3650
|
+
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended", {
|
|
3651
|
+
condition: "workflow-already-ended"
|
|
3652
|
+
});
|
|
3501
3653
|
}
|
|
3502
3654
|
await debug?.log("INFO", "RESPONSE_DEFAULT");
|
|
3503
|
-
return onStepFinish("no-workflow-id", "fromCallback"
|
|
3655
|
+
return onStepFinish("no-workflow-id", "fromCallback", {
|
|
3656
|
+
condition: "fromCallback"
|
|
3657
|
+
});
|
|
3504
3658
|
};
|
|
3505
3659
|
const safeHandler = async (request) => {
|
|
3506
3660
|
try {
|
|
@@ -3515,11 +3669,17 @@ var serveBase = (routeFunction, telemetry, options) => {
|
|
|
3515
3669
|
Original error: '${formattedError.message}'`;
|
|
3516
3670
|
console.error(errorMessage);
|
|
3517
3671
|
return new Response(errorMessage, {
|
|
3518
|
-
status: 500
|
|
3672
|
+
status: 500,
|
|
3673
|
+
headers: {
|
|
3674
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3675
|
+
}
|
|
3519
3676
|
});
|
|
3520
3677
|
}
|
|
3521
3678
|
return new Response(JSON.stringify(formattedError), {
|
|
3522
|
-
status: 500
|
|
3679
|
+
status: 500,
|
|
3680
|
+
headers: {
|
|
3681
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3682
|
+
}
|
|
3523
3683
|
});
|
|
3524
3684
|
}
|
|
3525
3685
|
};
|
|
@@ -3542,6 +3702,7 @@ export {
|
|
|
3542
3702
|
__toESM,
|
|
3543
3703
|
makeNotifyRequest,
|
|
3544
3704
|
makeGetWaitersRequest,
|
|
3705
|
+
WORKFLOW_LABEL_HEADER,
|
|
3545
3706
|
SDK_TELEMETRY,
|
|
3546
3707
|
WorkflowError,
|
|
3547
3708
|
WorkflowAbort,
|