@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/h3.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as h3 from 'h3';
|
|
2
|
-
import { R as RouteFunction, n as PublicServeOptions,
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { R as RouteFunction, n as PublicServeOptions, x as InvokableWorkflow } from './types-B7_5AkKQ.mjs';
|
|
3
|
+
import { s as serveManyBase } from './serve-many-CEUYWQvV.mjs';
|
|
4
4
|
import '@upstash/qstash';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'ai';
|
package/h3.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as h3 from 'h3';
|
|
2
|
-
import { R as RouteFunction, n as PublicServeOptions,
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { R as RouteFunction, n as PublicServeOptions, x as InvokableWorkflow } from './types-B7_5AkKQ.js';
|
|
3
|
+
import { s as serveManyBase } from './serve-many-BObe3pdI.js';
|
|
4
4
|
import '@upstash/qstash';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'ai';
|
package/h3.js
CHANGED
|
@@ -398,12 +398,13 @@ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
|
398
398
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
399
399
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
400
400
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
401
|
+
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
401
402
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
402
403
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
403
404
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
404
405
|
var NO_CONCURRENCY = 1;
|
|
405
406
|
var DEFAULT_RETRIES = 3;
|
|
406
|
-
var VERSION = "v0.2.
|
|
407
|
+
var VERSION = "v0.2.18";
|
|
407
408
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
408
409
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
409
410
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -933,6 +934,7 @@ var triggerFirstInvocation = async (params) => {
|
|
|
933
934
|
workflowUrl: workflowContext.url,
|
|
934
935
|
failureUrl: workflowContext.failureUrl,
|
|
935
936
|
retries: workflowContext.retries,
|
|
937
|
+
retryDelay: workflowContext.retryDelay,
|
|
936
938
|
telemetry: telemetry2,
|
|
937
939
|
flowControl: workflowContext.flowControl,
|
|
938
940
|
useJSONContent: useJSONContent ?? false
|
|
@@ -946,6 +948,9 @@ var triggerFirstInvocation = async (params) => {
|
|
|
946
948
|
if (useJSONContent) {
|
|
947
949
|
headers["content-type"] = "application/json";
|
|
948
950
|
}
|
|
951
|
+
if (workflowContext.label) {
|
|
952
|
+
headers[WORKFLOW_LABEL_HEADER] = workflowContext.label;
|
|
953
|
+
}
|
|
949
954
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
950
955
|
return {
|
|
951
956
|
headers,
|
|
@@ -1046,10 +1051,11 @@ var recreateUserHeaders = (headers) => {
|
|
|
1046
1051
|
const pairs = headers.entries();
|
|
1047
1052
|
for (const [header, value] of pairs) {
|
|
1048
1053
|
const headerLowerCase = header.toLowerCase();
|
|
1049
|
-
|
|
1054
|
+
const isUserHeader = !headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
1050
1055
|
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
1051
1056
|
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
1052
|
-
headerLowerCase !== "render-proxy-ttl")
|
|
1057
|
+
headerLowerCase !== "render-proxy-ttl" || headerLowerCase === WORKFLOW_LABEL_HEADER.toLocaleLowerCase();
|
|
1058
|
+
if (isUserHeader) {
|
|
1053
1059
|
filteredHeaders.append(header, value);
|
|
1054
1060
|
}
|
|
1055
1061
|
}
|
|
@@ -1062,6 +1068,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
1062
1068
|
workflowUrl,
|
|
1063
1069
|
failureUrl,
|
|
1064
1070
|
retries,
|
|
1071
|
+
retryDelay,
|
|
1065
1072
|
telemetry: telemetry2,
|
|
1066
1073
|
flowControl,
|
|
1067
1074
|
debug
|
|
@@ -1132,6 +1139,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
1132
1139
|
workflowUrl,
|
|
1133
1140
|
failureUrl,
|
|
1134
1141
|
retries,
|
|
1142
|
+
retryDelay,
|
|
1135
1143
|
telemetry: telemetry2,
|
|
1136
1144
|
flowControl
|
|
1137
1145
|
},
|
|
@@ -1282,7 +1290,8 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1282
1290
|
workflowRunId: context.workflowRunId,
|
|
1283
1291
|
workflowUrl: context.url,
|
|
1284
1292
|
failureUrl: context.failureUrl,
|
|
1285
|
-
retries: context.retries,
|
|
1293
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1294
|
+
retryDelay: context.retryDelay,
|
|
1286
1295
|
useJSONContent: false,
|
|
1287
1296
|
telemetry: telemetry2,
|
|
1288
1297
|
flowControl: context.flowControl
|
|
@@ -1301,6 +1310,9 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1301
1310
|
body,
|
|
1302
1311
|
headers,
|
|
1303
1312
|
method: "POST",
|
|
1313
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1314
|
+
retryDelay: context.retryDelay,
|
|
1315
|
+
flowControl: context.flowControl,
|
|
1304
1316
|
url: context.url
|
|
1305
1317
|
}
|
|
1306
1318
|
]);
|
|
@@ -1371,6 +1383,9 @@ var LazySleepStep = class extends BaseLazyStep {
|
|
|
1371
1383
|
headers,
|
|
1372
1384
|
method: "POST",
|
|
1373
1385
|
url: context.url,
|
|
1386
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1387
|
+
retryDelay: context.retryDelay,
|
|
1388
|
+
flowControl: context.flowControl,
|
|
1374
1389
|
delay: isParallel ? void 0 : this.sleep
|
|
1375
1390
|
}
|
|
1376
1391
|
]);
|
|
@@ -1413,6 +1428,9 @@ var LazySleepUntilStep = class extends BaseLazyStep {
|
|
|
1413
1428
|
headers,
|
|
1414
1429
|
method: "POST",
|
|
1415
1430
|
url: context.url,
|
|
1431
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1432
|
+
retryDelay: context.retryDelay,
|
|
1433
|
+
flowControl: context.flowControl,
|
|
1416
1434
|
notBefore: isParallel ? void 0 : this.sleepUntil
|
|
1417
1435
|
}
|
|
1418
1436
|
]);
|
|
@@ -1424,17 +1442,19 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1424
1442
|
body;
|
|
1425
1443
|
headers;
|
|
1426
1444
|
retries;
|
|
1445
|
+
retryDelay;
|
|
1427
1446
|
timeout;
|
|
1428
1447
|
flowControl;
|
|
1429
1448
|
stepType = "Call";
|
|
1430
1449
|
allowUndefinedOut = false;
|
|
1431
|
-
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
1450
|
+
constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl) {
|
|
1432
1451
|
super(stepName);
|
|
1433
1452
|
this.url = url;
|
|
1434
1453
|
this.method = method;
|
|
1435
1454
|
this.body = body;
|
|
1436
1455
|
this.headers = headers;
|
|
1437
1456
|
this.retries = retries;
|
|
1457
|
+
this.retryDelay = retryDelay;
|
|
1438
1458
|
this.timeout = timeout;
|
|
1439
1459
|
this.flowControl = flowControl;
|
|
1440
1460
|
}
|
|
@@ -1509,6 +1529,9 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1509
1529
|
getHeaders({ context, telemetry: telemetry2, invokeCount, step }) {
|
|
1510
1530
|
const { headers, contentType } = super.getHeaders({ context, telemetry: telemetry2, invokeCount, step });
|
|
1511
1531
|
headers["Upstash-Retries"] = this.retries.toString();
|
|
1532
|
+
if (this.retryDelay) {
|
|
1533
|
+
headers["Upstash-Retry-Delay"] = this.retryDelay;
|
|
1534
|
+
}
|
|
1512
1535
|
headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
1513
1536
|
if (this.flowControl) {
|
|
1514
1537
|
const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
|
|
@@ -1530,7 +1553,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1530
1553
|
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1531
1554
|
"Upstash-Callback-Workflow-Init": "false",
|
|
1532
1555
|
"Upstash-Callback-Workflow-Url": context.url,
|
|
1533
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1556
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1534
1557
|
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1535
1558
|
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1536
1559
|
"Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
|
|
@@ -1548,7 +1571,10 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1548
1571
|
headers,
|
|
1549
1572
|
body: JSON.stringify(this.body),
|
|
1550
1573
|
method: this.method,
|
|
1551
|
-
url: this.url
|
|
1574
|
+
url: this.url,
|
|
1575
|
+
retries: DEFAULT_RETRIES === this.retries ? void 0 : this.retries,
|
|
1576
|
+
retryDelay: this.retryDelay,
|
|
1577
|
+
flowControl: this.flowControl
|
|
1552
1578
|
}
|
|
1553
1579
|
]);
|
|
1554
1580
|
}
|
|
@@ -1677,6 +1703,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1677
1703
|
headers = {},
|
|
1678
1704
|
workflowRunId,
|
|
1679
1705
|
retries,
|
|
1706
|
+
retryDelay,
|
|
1680
1707
|
flowControl
|
|
1681
1708
|
}) {
|
|
1682
1709
|
super(stepName);
|
|
@@ -1686,6 +1713,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1686
1713
|
headers,
|
|
1687
1714
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1688
1715
|
retries,
|
|
1716
|
+
retryDelay,
|
|
1689
1717
|
flowControl
|
|
1690
1718
|
};
|
|
1691
1719
|
const { workflowId } = workflow;
|
|
@@ -1730,6 +1758,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1730
1758
|
workflowUrl: context.url,
|
|
1731
1759
|
failureUrl: context.failureUrl,
|
|
1732
1760
|
retries: context.retries,
|
|
1761
|
+
retryDelay: context.retryDelay,
|
|
1733
1762
|
telemetry: telemetry2,
|
|
1734
1763
|
flowControl: context.flowControl,
|
|
1735
1764
|
useJSONContent: false
|
|
@@ -1755,11 +1784,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1755
1784
|
headers = {},
|
|
1756
1785
|
workflowRunId = getWorkflowRunId(),
|
|
1757
1786
|
retries,
|
|
1787
|
+
retryDelay,
|
|
1758
1788
|
flowControl
|
|
1759
1789
|
} = this.params;
|
|
1760
1790
|
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1761
1791
|
const {
|
|
1762
1792
|
retries: workflowRetries,
|
|
1793
|
+
retryDelay: workflowRetryDelay,
|
|
1763
1794
|
failureFunction,
|
|
1764
1795
|
failureUrl,
|
|
1765
1796
|
useJSONContent,
|
|
@@ -1771,6 +1802,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1771
1802
|
workflowRunId,
|
|
1772
1803
|
workflowUrl: newUrl,
|
|
1773
1804
|
retries: retries ?? workflowRetries,
|
|
1805
|
+
retryDelay: retryDelay ?? workflowRetryDelay,
|
|
1774
1806
|
telemetry: telemetry2,
|
|
1775
1807
|
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1776
1808
|
flowControl: flowControl ?? workflowFlowControl,
|
|
@@ -1837,6 +1869,7 @@ var WorkflowHeaders = class {
|
|
|
1837
1869
|
getHeaders() {
|
|
1838
1870
|
this.addBaseHeaders();
|
|
1839
1871
|
this.addRetries();
|
|
1872
|
+
this.addRetryDelay();
|
|
1840
1873
|
this.addFlowControl();
|
|
1841
1874
|
this.addUserHeaders();
|
|
1842
1875
|
this.addInvokeCount();
|
|
@@ -1850,7 +1883,7 @@ var WorkflowHeaders = class {
|
|
|
1850
1883
|
[WORKFLOW_INIT_HEADER]: this.initHeaderValue,
|
|
1851
1884
|
[WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
|
|
1852
1885
|
[WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
|
|
1853
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1886
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1854
1887
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1855
1888
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
|
|
1856
1889
|
...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
|
|
@@ -1882,6 +1915,16 @@ var WorkflowHeaders = class {
|
|
|
1882
1915
|
this.headers.failureHeaders["Retries"] = retries;
|
|
1883
1916
|
}
|
|
1884
1917
|
}
|
|
1918
|
+
addRetryDelay() {
|
|
1919
|
+
if (this.workflowConfig.retryDelay === void 0 || this.workflowConfig.retryDelay === "") {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
const retryDelay = this.workflowConfig.retryDelay.toString();
|
|
1923
|
+
this.headers.workflowHeaders["Retry-Delay"] = retryDelay;
|
|
1924
|
+
if (this.workflowConfig.failureUrl) {
|
|
1925
|
+
this.headers.failureHeaders["Retry-Delay"] = retryDelay;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1885
1928
|
addFlowControl() {
|
|
1886
1929
|
if (!this.workflowConfig.flowControl) {
|
|
1887
1930
|
return;
|
|
@@ -1916,10 +1959,13 @@ var WorkflowHeaders = class {
|
|
|
1916
1959
|
this.headers.failureHeaders["Workflow-Init"] = "false";
|
|
1917
1960
|
this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
|
|
1918
1961
|
this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
|
|
1919
|
-
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
|
|
1962
|
+
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody,WF_DetectTrigger";
|
|
1920
1963
|
if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
|
|
1921
1964
|
this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
|
|
1922
1965
|
}
|
|
1966
|
+
if (this.workflowConfig.retryDelay !== void 0 && this.workflowConfig.retryDelay !== "") {
|
|
1967
|
+
this.headers.failureHeaders["Retry-Delay"] = this.workflowConfig.retryDelay.toString();
|
|
1968
|
+
}
|
|
1923
1969
|
}
|
|
1924
1970
|
addContentType() {
|
|
1925
1971
|
if (this.workflowConfig.useJSONContent) {
|
|
@@ -2001,6 +2047,7 @@ var submitParallelSteps = async ({
|
|
|
2001
2047
|
workflowUrl: context.url,
|
|
2002
2048
|
failureUrl: context.failureUrl,
|
|
2003
2049
|
retries: context.retries,
|
|
2050
|
+
retryDelay: context.retryDelay,
|
|
2004
2051
|
flowControl: context.flowControl,
|
|
2005
2052
|
telemetry: telemetry2
|
|
2006
2053
|
},
|
|
@@ -2421,7 +2468,7 @@ var BaseWorkflowApi = class {
|
|
|
2421
2468
|
*/
|
|
2422
2469
|
async callApi(stepName, settings) {
|
|
2423
2470
|
const { url, appendHeaders, method } = getProviderInfo(settings.api);
|
|
2424
|
-
const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
|
|
2471
|
+
const { method: userMethod, body, headers = {}, retries = 0, retryDelay, timeout } = settings;
|
|
2425
2472
|
return await this.context.call(stepName, {
|
|
2426
2473
|
url,
|
|
2427
2474
|
method: userMethod ?? method,
|
|
@@ -2431,6 +2478,7 @@ var BaseWorkflowApi = class {
|
|
|
2431
2478
|
...headers
|
|
2432
2479
|
},
|
|
2433
2480
|
retries,
|
|
2481
|
+
retryDelay,
|
|
2434
2482
|
timeout
|
|
2435
2483
|
});
|
|
2436
2484
|
}
|
|
@@ -2520,6 +2568,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
2520
2568
|
body,
|
|
2521
2569
|
timeout: agentCallParams?.timeout,
|
|
2522
2570
|
retries: agentCallParams?.retries,
|
|
2571
|
+
retryDelay: agentCallParams?.retryDelay,
|
|
2523
2572
|
flowControl: agentCallParams?.flowControl
|
|
2524
2573
|
});
|
|
2525
2574
|
const responseHeaders = new Headers(
|
|
@@ -2848,7 +2897,10 @@ var serveManyBase = ({
|
|
|
2848
2897
|
return new Response(
|
|
2849
2898
|
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
2850
2899
|
{
|
|
2851
|
-
status: 404
|
|
2900
|
+
status: 404,
|
|
2901
|
+
headers: {
|
|
2902
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
2903
|
+
}
|
|
2852
2904
|
}
|
|
2853
2905
|
);
|
|
2854
2906
|
}
|
|
@@ -2857,7 +2909,10 @@ var serveManyBase = ({
|
|
|
2857
2909
|
return new Response(
|
|
2858
2910
|
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
2859
2911
|
{
|
|
2860
|
-
status: 404
|
|
2912
|
+
status: 404,
|
|
2913
|
+
headers: {
|
|
2914
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
2915
|
+
}
|
|
2861
2916
|
}
|
|
2862
2917
|
);
|
|
2863
2918
|
}
|
|
@@ -2994,11 +3049,58 @@ var WorkflowContext = class {
|
|
|
2994
3049
|
* Number of retries
|
|
2995
3050
|
*/
|
|
2996
3051
|
retries;
|
|
3052
|
+
/**
|
|
3053
|
+
* Delay between retries.
|
|
3054
|
+
*
|
|
3055
|
+
* By default, the `retryDelay` is exponential backoff.
|
|
3056
|
+
* More details can be found in: https://upstash.com/docs/qstash/features/retry.
|
|
3057
|
+
*
|
|
3058
|
+
* The `retryDelay` option allows you to customize the delay (in milliseconds) between retry attempts when message delivery fails.
|
|
3059
|
+
*
|
|
3060
|
+
* You can use mathematical expressions and the following built-in functions to calculate the delay dynamically.
|
|
3061
|
+
* The special variable `retried` represents the current retry attempt count (starting from 0).
|
|
3062
|
+
*
|
|
3063
|
+
* Supported functions:
|
|
3064
|
+
* - `pow`
|
|
3065
|
+
* - `sqrt`
|
|
3066
|
+
* - `abs`
|
|
3067
|
+
* - `exp`
|
|
3068
|
+
* - `floor`
|
|
3069
|
+
* - `ceil`
|
|
3070
|
+
* - `round`
|
|
3071
|
+
* - `min`
|
|
3072
|
+
* - `max`
|
|
3073
|
+
*
|
|
3074
|
+
* Examples of valid `retryDelay` values:
|
|
3075
|
+
* ```ts
|
|
3076
|
+
* 1000 // 1 second
|
|
3077
|
+
* 1000 * (1 + retried) // 1 second multiplied by the current retry attempt
|
|
3078
|
+
* pow(2, retried) // 2 to the power of the current retry attempt
|
|
3079
|
+
* max(10, pow(2, retried)) // The greater of 10 or 2^retried
|
|
3080
|
+
* ```
|
|
3081
|
+
*/
|
|
3082
|
+
retryDelay;
|
|
2997
3083
|
/**
|
|
2998
3084
|
* Settings for controlling the number of active requests
|
|
2999
3085
|
* and number of requests per second with the same key.
|
|
3000
3086
|
*/
|
|
3001
3087
|
flowControl;
|
|
3088
|
+
/**
|
|
3089
|
+
* Label to apply to the workflow run.
|
|
3090
|
+
*
|
|
3091
|
+
* Can be used to filter the workflow run logs.
|
|
3092
|
+
*
|
|
3093
|
+
* Can be set by passing a `label` parameter when triggering the workflow
|
|
3094
|
+
* with `client.trigger`:
|
|
3095
|
+
*
|
|
3096
|
+
* ```ts
|
|
3097
|
+
* await client.trigger({
|
|
3098
|
+
* url: "https://workflow-endpoint.com",
|
|
3099
|
+
* label: "my-label"
|
|
3100
|
+
* });
|
|
3101
|
+
* ```
|
|
3102
|
+
*/
|
|
3103
|
+
label;
|
|
3002
3104
|
constructor({
|
|
3003
3105
|
qstashClient,
|
|
3004
3106
|
workflowRunId,
|
|
@@ -3010,9 +3112,11 @@ var WorkflowContext = class {
|
|
|
3010
3112
|
initialPayload,
|
|
3011
3113
|
env,
|
|
3012
3114
|
retries,
|
|
3115
|
+
retryDelay,
|
|
3013
3116
|
telemetry: telemetry2,
|
|
3014
3117
|
invokeCount,
|
|
3015
|
-
flowControl
|
|
3118
|
+
flowControl,
|
|
3119
|
+
label
|
|
3016
3120
|
}) {
|
|
3017
3121
|
this.qstashClient = qstashClient;
|
|
3018
3122
|
this.workflowRunId = workflowRunId;
|
|
@@ -3023,7 +3127,9 @@ var WorkflowContext = class {
|
|
|
3023
3127
|
this.requestPayload = initialPayload;
|
|
3024
3128
|
this.env = env ?? {};
|
|
3025
3129
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
3130
|
+
this.retryDelay = retryDelay;
|
|
3026
3131
|
this.flowControl = flowControl;
|
|
3132
|
+
this.label = label;
|
|
3027
3133
|
this.executor = new AutoExecutor(this, this.steps, telemetry2, invokeCount, debug);
|
|
3028
3134
|
}
|
|
3029
3135
|
/**
|
|
@@ -3104,6 +3210,7 @@ var WorkflowContext = class {
|
|
|
3104
3210
|
settings.body,
|
|
3105
3211
|
settings.headers || {},
|
|
3106
3212
|
settings.retries || 0,
|
|
3213
|
+
settings.retryDelay,
|
|
3107
3214
|
settings.timeout,
|
|
3108
3215
|
settings.flowControl ?? settings.workflow.options.flowControl
|
|
3109
3216
|
);
|
|
@@ -3114,6 +3221,7 @@ var WorkflowContext = class {
|
|
|
3114
3221
|
body,
|
|
3115
3222
|
headers = {},
|
|
3116
3223
|
retries = 0,
|
|
3224
|
+
retryDelay,
|
|
3117
3225
|
timeout,
|
|
3118
3226
|
flowControl
|
|
3119
3227
|
} = settings;
|
|
@@ -3124,6 +3232,7 @@ var WorkflowContext = class {
|
|
|
3124
3232
|
body,
|
|
3125
3233
|
headers,
|
|
3126
3234
|
retries,
|
|
3235
|
+
retryDelay,
|
|
3127
3236
|
timeout,
|
|
3128
3237
|
flowControl
|
|
3129
3238
|
);
|
|
@@ -3134,7 +3243,7 @@ var WorkflowContext = class {
|
|
|
3134
3243
|
* Pauses workflow execution until a specific event occurs or a timeout is reached.
|
|
3135
3244
|
*
|
|
3136
3245
|
*```ts
|
|
3137
|
-
* const result = await workflow.waitForEvent("payment-confirmed", {
|
|
3246
|
+
* const result = await workflow.waitForEvent("payment-confirmed", "payment.confirmed", {
|
|
3138
3247
|
* timeout: "5m"
|
|
3139
3248
|
* });
|
|
3140
3249
|
*```
|
|
@@ -3160,7 +3269,7 @@ var WorkflowContext = class {
|
|
|
3160
3269
|
* @param stepName
|
|
3161
3270
|
* @param eventId - Unique identifier for the event to wait for
|
|
3162
3271
|
* @param options - Configuration options.
|
|
3163
|
-
* @returns `{ timeout: boolean, eventData:
|
|
3272
|
+
* @returns `{ timeout: boolean, eventData: TEventData }`.
|
|
3164
3273
|
* The `timeout` property specifies if the workflow has timed out. The `eventData`
|
|
3165
3274
|
* is the data passed when notifying this workflow of an event.
|
|
3166
3275
|
*/
|
|
@@ -3320,7 +3429,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3320
3429
|
initialPayload: context.requestPayload,
|
|
3321
3430
|
env: context.env,
|
|
3322
3431
|
retries: context.retries,
|
|
3323
|
-
|
|
3432
|
+
retryDelay: context.retryDelay,
|
|
3433
|
+
flowControl: context.flowControl,
|
|
3434
|
+
label: context.label
|
|
3324
3435
|
});
|
|
3325
3436
|
try {
|
|
3326
3437
|
await routeFunction(disabledContext);
|
|
@@ -3328,6 +3439,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3328
3439
|
if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
|
|
3329
3440
|
return ok("step-found");
|
|
3330
3441
|
}
|
|
3442
|
+
console.warn(
|
|
3443
|
+
"Upstash Workflow: Received an error while authorizing request. Please avoid throwing errors before the first step of your workflow."
|
|
3444
|
+
);
|
|
3331
3445
|
return err(error);
|
|
3332
3446
|
}
|
|
3333
3447
|
return ok("run-ended");
|
|
@@ -3469,9 +3583,9 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
3469
3583
|
};
|
|
3470
3584
|
}
|
|
3471
3585
|
};
|
|
3472
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
3586
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, retryDelay, flowControl, debug) => {
|
|
3473
3587
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
3474
|
-
return ok("not-failure-callback");
|
|
3588
|
+
return ok({ result: "not-failure-callback" });
|
|
3475
3589
|
}
|
|
3476
3590
|
if (!failureFunction) {
|
|
3477
3591
|
return err(
|
|
@@ -3494,20 +3608,23 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3494
3608
|
if (!errorMessage) {
|
|
3495
3609
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3496
3610
|
}
|
|
3611
|
+
const userHeaders = recreateUserHeaders(request.headers);
|
|
3497
3612
|
const workflowContext = new WorkflowContext({
|
|
3498
3613
|
qstashClient,
|
|
3499
3614
|
workflowRunId,
|
|
3500
3615
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
3501
|
-
headers:
|
|
3616
|
+
headers: userHeaders,
|
|
3502
3617
|
steps: [],
|
|
3503
3618
|
url,
|
|
3504
3619
|
failureUrl: url,
|
|
3505
3620
|
debug,
|
|
3506
3621
|
env,
|
|
3507
3622
|
retries,
|
|
3623
|
+
retryDelay,
|
|
3508
3624
|
flowControl,
|
|
3509
|
-
telemetry: void 0
|
|
3625
|
+
telemetry: void 0,
|
|
3510
3626
|
// not going to make requests in authentication check
|
|
3627
|
+
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0
|
|
3511
3628
|
});
|
|
3512
3629
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3513
3630
|
routeFunction,
|
|
@@ -3519,16 +3636,16 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3519
3636
|
} else if (authCheck.value === "run-ended") {
|
|
3520
3637
|
return err(new WorkflowError("Not authorized to run the failure function."));
|
|
3521
3638
|
}
|
|
3522
|
-
await failureFunction({
|
|
3639
|
+
const failureResponse = await failureFunction({
|
|
3523
3640
|
context: workflowContext,
|
|
3524
3641
|
failStatus: status,
|
|
3525
3642
|
failResponse: errorMessage,
|
|
3526
3643
|
failHeaders: header
|
|
3527
3644
|
});
|
|
3645
|
+
return ok({ result: "is-failure-callback", response: failureResponse });
|
|
3528
3646
|
} catch (error) {
|
|
3529
3647
|
return err(error);
|
|
3530
3648
|
}
|
|
3531
|
-
return ok("is-failure-callback");
|
|
3532
3649
|
};
|
|
3533
3650
|
|
|
3534
3651
|
// src/serve/options.ts
|
|
@@ -3544,8 +3661,8 @@ var processOptions = (options) => {
|
|
|
3544
3661
|
baseUrl: environment.QSTASH_URL,
|
|
3545
3662
|
token: environment.QSTASH_TOKEN
|
|
3546
3663
|
}),
|
|
3547
|
-
onStepFinish: (workflowRunId,
|
|
3548
|
-
if (
|
|
3664
|
+
onStepFinish: (workflowRunId, _finishCondition, detailedFinishCondition) => {
|
|
3665
|
+
if (detailedFinishCondition?.condition === "auth-fail") {
|
|
3549
3666
|
console.error(AUTH_FAIL_MESSAGE);
|
|
3550
3667
|
return new Response(
|
|
3551
3668
|
JSON.stringify({
|
|
@@ -3553,19 +3670,33 @@ var processOptions = (options) => {
|
|
|
3553
3670
|
workflowRunId
|
|
3554
3671
|
}),
|
|
3555
3672
|
{
|
|
3556
|
-
status: 400
|
|
3673
|
+
status: 400,
|
|
3674
|
+
headers: {
|
|
3675
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3676
|
+
}
|
|
3557
3677
|
}
|
|
3558
3678
|
);
|
|
3559
|
-
} else if (
|
|
3560
|
-
return new Response(JSON.stringify(formatWorkflowError(
|
|
3679
|
+
} else if (detailedFinishCondition?.condition === "non-retryable-error") {
|
|
3680
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3561
3681
|
headers: {
|
|
3562
|
-
"Upstash-NonRetryable-Error": "true"
|
|
3682
|
+
"Upstash-NonRetryable-Error": "true",
|
|
3683
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3563
3684
|
},
|
|
3564
3685
|
status: 489
|
|
3565
3686
|
});
|
|
3687
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3688
|
+
return new Response(detailedFinishCondition.result ?? void 0, {
|
|
3689
|
+
status: 200,
|
|
3690
|
+
headers: {
|
|
3691
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3692
|
+
}
|
|
3693
|
+
});
|
|
3566
3694
|
}
|
|
3567
3695
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3568
|
-
status: 200
|
|
3696
|
+
status: 200,
|
|
3697
|
+
headers: {
|
|
3698
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3699
|
+
}
|
|
3569
3700
|
});
|
|
3570
3701
|
},
|
|
3571
3702
|
initialPayloadParser: (initialRequest) => {
|
|
@@ -3639,6 +3770,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3639
3770
|
baseUrl,
|
|
3640
3771
|
env,
|
|
3641
3772
|
retries,
|
|
3773
|
+
retryDelay,
|
|
3642
3774
|
useJSONContent,
|
|
3643
3775
|
disableTelemetry,
|
|
3644
3776
|
flowControl,
|
|
@@ -3669,10 +3801,14 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3669
3801
|
debug
|
|
3670
3802
|
);
|
|
3671
3803
|
if (workflowRunEnded) {
|
|
3672
|
-
return onStepFinish(workflowRunId, "workflow-already-ended"
|
|
3804
|
+
return onStepFinish(workflowRunId, "workflow-already-ended", {
|
|
3805
|
+
condition: "workflow-already-ended"
|
|
3806
|
+
});
|
|
3673
3807
|
}
|
|
3674
3808
|
if (isLastDuplicate) {
|
|
3675
|
-
return onStepFinish(workflowRunId, "duplicate-step"
|
|
3809
|
+
return onStepFinish(workflowRunId, "duplicate-step", {
|
|
3810
|
+
condition: "duplicate-step"
|
|
3811
|
+
});
|
|
3676
3812
|
}
|
|
3677
3813
|
const failureCheck = await handleFailure(
|
|
3678
3814
|
request,
|
|
@@ -3683,16 +3819,21 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3683
3819
|
failureFunction,
|
|
3684
3820
|
env,
|
|
3685
3821
|
retries,
|
|
3822
|
+
retryDelay,
|
|
3686
3823
|
flowControl,
|
|
3687
3824
|
debug
|
|
3688
3825
|
);
|
|
3689
3826
|
if (failureCheck.isErr()) {
|
|
3690
3827
|
throw failureCheck.error;
|
|
3691
|
-
} else if (failureCheck.value === "is-failure-callback") {
|
|
3828
|
+
} else if (failureCheck.value.result === "is-failure-callback") {
|
|
3692
3829
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
3693
|
-
return onStepFinish(workflowRunId, "failure-callback"
|
|
3830
|
+
return onStepFinish(workflowRunId, "failure-callback", {
|
|
3831
|
+
condition: "failure-callback",
|
|
3832
|
+
result: failureCheck.value.response
|
|
3833
|
+
});
|
|
3694
3834
|
}
|
|
3695
3835
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3836
|
+
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3696
3837
|
const workflowContext = new WorkflowContext({
|
|
3697
3838
|
qstashClient,
|
|
3698
3839
|
workflowRunId,
|
|
@@ -3704,9 +3845,11 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3704
3845
|
debug,
|
|
3705
3846
|
env,
|
|
3706
3847
|
retries,
|
|
3848
|
+
retryDelay,
|
|
3707
3849
|
telemetry: telemetry2,
|
|
3708
3850
|
invokeCount,
|
|
3709
|
-
flowControl
|
|
3851
|
+
flowControl,
|
|
3852
|
+
label
|
|
3710
3853
|
});
|
|
3711
3854
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3712
3855
|
routeFunction,
|
|
@@ -3719,7 +3862,8 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3719
3862
|
await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
|
|
3720
3863
|
return onStepFinish(
|
|
3721
3864
|
isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
|
|
3722
|
-
"auth-fail"
|
|
3865
|
+
"auth-fail",
|
|
3866
|
+
{ condition: "auth-fail" }
|
|
3723
3867
|
);
|
|
3724
3868
|
}
|
|
3725
3869
|
const callReturnCheck = await handleThirdPartyCallResult({
|
|
@@ -3729,6 +3873,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3729
3873
|
workflowUrl,
|
|
3730
3874
|
failureUrl: workflowFailureUrl,
|
|
3731
3875
|
retries,
|
|
3876
|
+
retryDelay,
|
|
3732
3877
|
flowControl,
|
|
3733
3878
|
telemetry: telemetry2,
|
|
3734
3879
|
debug
|
|
@@ -3756,19 +3901,28 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3756
3901
|
debug
|
|
3757
3902
|
});
|
|
3758
3903
|
if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
|
|
3759
|
-
return onStepFinish(workflowRunId, result.value
|
|
3904
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
3905
|
+
condition: "non-retryable-error",
|
|
3906
|
+
result: result.value
|
|
3907
|
+
});
|
|
3760
3908
|
}
|
|
3761
3909
|
if (result.isErr()) {
|
|
3762
3910
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3763
3911
|
throw result.error;
|
|
3764
3912
|
}
|
|
3765
3913
|
await debug?.log("INFO", "RESPONSE_WORKFLOW");
|
|
3766
|
-
return onStepFinish(workflowContext.workflowRunId, "success"
|
|
3914
|
+
return onStepFinish(workflowContext.workflowRunId, "success", {
|
|
3915
|
+
condition: "success"
|
|
3916
|
+
});
|
|
3767
3917
|
} else if (callReturnCheck.value === "workflow-ended") {
|
|
3768
|
-
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended"
|
|
3918
|
+
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended", {
|
|
3919
|
+
condition: "workflow-already-ended"
|
|
3920
|
+
});
|
|
3769
3921
|
}
|
|
3770
3922
|
await debug?.log("INFO", "RESPONSE_DEFAULT");
|
|
3771
|
-
return onStepFinish("no-workflow-id", "fromCallback"
|
|
3923
|
+
return onStepFinish("no-workflow-id", "fromCallback", {
|
|
3924
|
+
condition: "fromCallback"
|
|
3925
|
+
});
|
|
3772
3926
|
};
|
|
3773
3927
|
const safeHandler = async (request) => {
|
|
3774
3928
|
try {
|
|
@@ -3783,11 +3937,17 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3783
3937
|
Original error: '${formattedError.message}'`;
|
|
3784
3938
|
console.error(errorMessage);
|
|
3785
3939
|
return new Response(errorMessage, {
|
|
3786
|
-
status: 500
|
|
3940
|
+
status: 500,
|
|
3941
|
+
headers: {
|
|
3942
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3943
|
+
}
|
|
3787
3944
|
});
|
|
3788
3945
|
}
|
|
3789
3946
|
return new Response(JSON.stringify(formattedError), {
|
|
3790
|
-
status: 500
|
|
3947
|
+
status: 500,
|
|
3948
|
+
headers: {
|
|
3949
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3950
|
+
}
|
|
3791
3951
|
});
|
|
3792
3952
|
}
|
|
3793
3953
|
};
|