@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.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APIContext, APIRoute } from 'astro';
|
|
2
|
-
import { g as WorkflowContext, n as PublicServeOptions,
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { g as WorkflowContext, 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/astro.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APIContext, APIRoute } from 'astro';
|
|
2
|
-
import { g as WorkflowContext, n as PublicServeOptions,
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { g as WorkflowContext, 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/astro.js
CHANGED
|
@@ -86,12 +86,13 @@ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
|
86
86
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
87
87
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
88
88
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
89
|
+
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
89
90
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
90
91
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
91
92
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
92
93
|
var NO_CONCURRENCY = 1;
|
|
93
94
|
var DEFAULT_RETRIES = 3;
|
|
94
|
-
var VERSION = "v0.2.
|
|
95
|
+
var VERSION = "v0.2.18";
|
|
95
96
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
96
97
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
97
98
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -621,6 +622,7 @@ var triggerFirstInvocation = async (params) => {
|
|
|
621
622
|
workflowUrl: workflowContext.url,
|
|
622
623
|
failureUrl: workflowContext.failureUrl,
|
|
623
624
|
retries: workflowContext.retries,
|
|
625
|
+
retryDelay: workflowContext.retryDelay,
|
|
624
626
|
telemetry: telemetry2,
|
|
625
627
|
flowControl: workflowContext.flowControl,
|
|
626
628
|
useJSONContent: useJSONContent ?? false
|
|
@@ -634,6 +636,9 @@ var triggerFirstInvocation = async (params) => {
|
|
|
634
636
|
if (useJSONContent) {
|
|
635
637
|
headers["content-type"] = "application/json";
|
|
636
638
|
}
|
|
639
|
+
if (workflowContext.label) {
|
|
640
|
+
headers[WORKFLOW_LABEL_HEADER] = workflowContext.label;
|
|
641
|
+
}
|
|
637
642
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
638
643
|
return {
|
|
639
644
|
headers,
|
|
@@ -734,10 +739,11 @@ var recreateUserHeaders = (headers) => {
|
|
|
734
739
|
const pairs = headers.entries();
|
|
735
740
|
for (const [header, value] of pairs) {
|
|
736
741
|
const headerLowerCase = header.toLowerCase();
|
|
737
|
-
|
|
742
|
+
const isUserHeader = !headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
|
|
738
743
|
!headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
|
|
739
744
|
headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
|
|
740
|
-
headerLowerCase !== "render-proxy-ttl")
|
|
745
|
+
headerLowerCase !== "render-proxy-ttl" || headerLowerCase === WORKFLOW_LABEL_HEADER.toLocaleLowerCase();
|
|
746
|
+
if (isUserHeader) {
|
|
741
747
|
filteredHeaders.append(header, value);
|
|
742
748
|
}
|
|
743
749
|
}
|
|
@@ -750,6 +756,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
750
756
|
workflowUrl,
|
|
751
757
|
failureUrl,
|
|
752
758
|
retries,
|
|
759
|
+
retryDelay,
|
|
753
760
|
telemetry: telemetry2,
|
|
754
761
|
flowControl,
|
|
755
762
|
debug
|
|
@@ -820,6 +827,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
820
827
|
workflowUrl,
|
|
821
828
|
failureUrl,
|
|
822
829
|
retries,
|
|
830
|
+
retryDelay,
|
|
823
831
|
telemetry: telemetry2,
|
|
824
832
|
flowControl
|
|
825
833
|
},
|
|
@@ -970,7 +978,8 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
970
978
|
workflowRunId: context.workflowRunId,
|
|
971
979
|
workflowUrl: context.url,
|
|
972
980
|
failureUrl: context.failureUrl,
|
|
973
|
-
retries: context.retries,
|
|
981
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
982
|
+
retryDelay: context.retryDelay,
|
|
974
983
|
useJSONContent: false,
|
|
975
984
|
telemetry: telemetry2,
|
|
976
985
|
flowControl: context.flowControl
|
|
@@ -989,6 +998,9 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
989
998
|
body,
|
|
990
999
|
headers,
|
|
991
1000
|
method: "POST",
|
|
1001
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1002
|
+
retryDelay: context.retryDelay,
|
|
1003
|
+
flowControl: context.flowControl,
|
|
992
1004
|
url: context.url
|
|
993
1005
|
}
|
|
994
1006
|
]);
|
|
@@ -1059,6 +1071,9 @@ var LazySleepStep = class extends BaseLazyStep {
|
|
|
1059
1071
|
headers,
|
|
1060
1072
|
method: "POST",
|
|
1061
1073
|
url: context.url,
|
|
1074
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1075
|
+
retryDelay: context.retryDelay,
|
|
1076
|
+
flowControl: context.flowControl,
|
|
1062
1077
|
delay: isParallel ? void 0 : this.sleep
|
|
1063
1078
|
}
|
|
1064
1079
|
]);
|
|
@@ -1101,6 +1116,9 @@ var LazySleepUntilStep = class extends BaseLazyStep {
|
|
|
1101
1116
|
headers,
|
|
1102
1117
|
method: "POST",
|
|
1103
1118
|
url: context.url,
|
|
1119
|
+
retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
|
|
1120
|
+
retryDelay: context.retryDelay,
|
|
1121
|
+
flowControl: context.flowControl,
|
|
1104
1122
|
notBefore: isParallel ? void 0 : this.sleepUntil
|
|
1105
1123
|
}
|
|
1106
1124
|
]);
|
|
@@ -1112,17 +1130,19 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1112
1130
|
body;
|
|
1113
1131
|
headers;
|
|
1114
1132
|
retries;
|
|
1133
|
+
retryDelay;
|
|
1115
1134
|
timeout;
|
|
1116
1135
|
flowControl;
|
|
1117
1136
|
stepType = "Call";
|
|
1118
1137
|
allowUndefinedOut = false;
|
|
1119
|
-
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
1138
|
+
constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl) {
|
|
1120
1139
|
super(stepName);
|
|
1121
1140
|
this.url = url;
|
|
1122
1141
|
this.method = method;
|
|
1123
1142
|
this.body = body;
|
|
1124
1143
|
this.headers = headers;
|
|
1125
1144
|
this.retries = retries;
|
|
1145
|
+
this.retryDelay = retryDelay;
|
|
1126
1146
|
this.timeout = timeout;
|
|
1127
1147
|
this.flowControl = flowControl;
|
|
1128
1148
|
}
|
|
@@ -1197,6 +1217,9 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1197
1217
|
getHeaders({ context, telemetry: telemetry2, invokeCount, step }) {
|
|
1198
1218
|
const { headers, contentType } = super.getHeaders({ context, telemetry: telemetry2, invokeCount, step });
|
|
1199
1219
|
headers["Upstash-Retries"] = this.retries.toString();
|
|
1220
|
+
if (this.retryDelay) {
|
|
1221
|
+
headers["Upstash-Retry-Delay"] = this.retryDelay;
|
|
1222
|
+
}
|
|
1200
1223
|
headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
1201
1224
|
if (this.flowControl) {
|
|
1202
1225
|
const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
|
|
@@ -1218,7 +1241,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1218
1241
|
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1219
1242
|
"Upstash-Callback-Workflow-Init": "false",
|
|
1220
1243
|
"Upstash-Callback-Workflow-Url": context.url,
|
|
1221
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1244
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1222
1245
|
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1223
1246
|
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1224
1247
|
"Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
|
|
@@ -1236,7 +1259,10 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1236
1259
|
headers,
|
|
1237
1260
|
body: JSON.stringify(this.body),
|
|
1238
1261
|
method: this.method,
|
|
1239
|
-
url: this.url
|
|
1262
|
+
url: this.url,
|
|
1263
|
+
retries: DEFAULT_RETRIES === this.retries ? void 0 : this.retries,
|
|
1264
|
+
retryDelay: this.retryDelay,
|
|
1265
|
+
flowControl: this.flowControl
|
|
1240
1266
|
}
|
|
1241
1267
|
]);
|
|
1242
1268
|
}
|
|
@@ -1365,6 +1391,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1365
1391
|
headers = {},
|
|
1366
1392
|
workflowRunId,
|
|
1367
1393
|
retries,
|
|
1394
|
+
retryDelay,
|
|
1368
1395
|
flowControl
|
|
1369
1396
|
}) {
|
|
1370
1397
|
super(stepName);
|
|
@@ -1374,6 +1401,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1374
1401
|
headers,
|
|
1375
1402
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1376
1403
|
retries,
|
|
1404
|
+
retryDelay,
|
|
1377
1405
|
flowControl
|
|
1378
1406
|
};
|
|
1379
1407
|
const { workflowId } = workflow;
|
|
@@ -1418,6 +1446,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1418
1446
|
workflowUrl: context.url,
|
|
1419
1447
|
failureUrl: context.failureUrl,
|
|
1420
1448
|
retries: context.retries,
|
|
1449
|
+
retryDelay: context.retryDelay,
|
|
1421
1450
|
telemetry: telemetry2,
|
|
1422
1451
|
flowControl: context.flowControl,
|
|
1423
1452
|
useJSONContent: false
|
|
@@ -1443,11 +1472,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1443
1472
|
headers = {},
|
|
1444
1473
|
workflowRunId = getWorkflowRunId(),
|
|
1445
1474
|
retries,
|
|
1475
|
+
retryDelay,
|
|
1446
1476
|
flowControl
|
|
1447
1477
|
} = this.params;
|
|
1448
1478
|
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1449
1479
|
const {
|
|
1450
1480
|
retries: workflowRetries,
|
|
1481
|
+
retryDelay: workflowRetryDelay,
|
|
1451
1482
|
failureFunction,
|
|
1452
1483
|
failureUrl,
|
|
1453
1484
|
useJSONContent,
|
|
@@ -1459,6 +1490,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1459
1490
|
workflowRunId,
|
|
1460
1491
|
workflowUrl: newUrl,
|
|
1461
1492
|
retries: retries ?? workflowRetries,
|
|
1493
|
+
retryDelay: retryDelay ?? workflowRetryDelay,
|
|
1462
1494
|
telemetry: telemetry2,
|
|
1463
1495
|
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1464
1496
|
flowControl: flowControl ?? workflowFlowControl,
|
|
@@ -1525,6 +1557,7 @@ var WorkflowHeaders = class {
|
|
|
1525
1557
|
getHeaders() {
|
|
1526
1558
|
this.addBaseHeaders();
|
|
1527
1559
|
this.addRetries();
|
|
1560
|
+
this.addRetryDelay();
|
|
1528
1561
|
this.addFlowControl();
|
|
1529
1562
|
this.addUserHeaders();
|
|
1530
1563
|
this.addInvokeCount();
|
|
@@ -1538,7 +1571,7 @@ var WorkflowHeaders = class {
|
|
|
1538
1571
|
[WORKFLOW_INIT_HEADER]: this.initHeaderValue,
|
|
1539
1572
|
[WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
|
|
1540
1573
|
[WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
|
|
1541
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1574
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger",
|
|
1542
1575
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1543
1576
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
|
|
1544
1577
|
...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
|
|
@@ -1570,6 +1603,16 @@ var WorkflowHeaders = class {
|
|
|
1570
1603
|
this.headers.failureHeaders["Retries"] = retries;
|
|
1571
1604
|
}
|
|
1572
1605
|
}
|
|
1606
|
+
addRetryDelay() {
|
|
1607
|
+
if (this.workflowConfig.retryDelay === void 0 || this.workflowConfig.retryDelay === "") {
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
const retryDelay = this.workflowConfig.retryDelay.toString();
|
|
1611
|
+
this.headers.workflowHeaders["Retry-Delay"] = retryDelay;
|
|
1612
|
+
if (this.workflowConfig.failureUrl) {
|
|
1613
|
+
this.headers.failureHeaders["Retry-Delay"] = retryDelay;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1573
1616
|
addFlowControl() {
|
|
1574
1617
|
if (!this.workflowConfig.flowControl) {
|
|
1575
1618
|
return;
|
|
@@ -1604,10 +1647,13 @@ var WorkflowHeaders = class {
|
|
|
1604
1647
|
this.headers.failureHeaders["Workflow-Init"] = "false";
|
|
1605
1648
|
this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
|
|
1606
1649
|
this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
|
|
1607
|
-
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
|
|
1650
|
+
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody,WF_DetectTrigger";
|
|
1608
1651
|
if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
|
|
1609
1652
|
this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
|
|
1610
1653
|
}
|
|
1654
|
+
if (this.workflowConfig.retryDelay !== void 0 && this.workflowConfig.retryDelay !== "") {
|
|
1655
|
+
this.headers.failureHeaders["Retry-Delay"] = this.workflowConfig.retryDelay.toString();
|
|
1656
|
+
}
|
|
1611
1657
|
}
|
|
1612
1658
|
addContentType() {
|
|
1613
1659
|
if (this.workflowConfig.useJSONContent) {
|
|
@@ -1689,6 +1735,7 @@ var submitParallelSteps = async ({
|
|
|
1689
1735
|
workflowUrl: context.url,
|
|
1690
1736
|
failureUrl: context.failureUrl,
|
|
1691
1737
|
retries: context.retries,
|
|
1738
|
+
retryDelay: context.retryDelay,
|
|
1692
1739
|
flowControl: context.flowControl,
|
|
1693
1740
|
telemetry: telemetry2
|
|
1694
1741
|
},
|
|
@@ -2109,7 +2156,7 @@ var BaseWorkflowApi = class {
|
|
|
2109
2156
|
*/
|
|
2110
2157
|
async callApi(stepName, settings) {
|
|
2111
2158
|
const { url, appendHeaders, method } = getProviderInfo(settings.api);
|
|
2112
|
-
const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
|
|
2159
|
+
const { method: userMethod, body, headers = {}, retries = 0, retryDelay, timeout } = settings;
|
|
2113
2160
|
return await this.context.call(stepName, {
|
|
2114
2161
|
url,
|
|
2115
2162
|
method: userMethod ?? method,
|
|
@@ -2119,6 +2166,7 @@ var BaseWorkflowApi = class {
|
|
|
2119
2166
|
...headers
|
|
2120
2167
|
},
|
|
2121
2168
|
retries,
|
|
2169
|
+
retryDelay,
|
|
2122
2170
|
timeout
|
|
2123
2171
|
});
|
|
2124
2172
|
}
|
|
@@ -2208,6 +2256,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
2208
2256
|
body,
|
|
2209
2257
|
timeout: agentCallParams?.timeout,
|
|
2210
2258
|
retries: agentCallParams?.retries,
|
|
2259
|
+
retryDelay: agentCallParams?.retryDelay,
|
|
2211
2260
|
flowControl: agentCallParams?.flowControl
|
|
2212
2261
|
});
|
|
2213
2262
|
const responseHeaders = new Headers(
|
|
@@ -2536,7 +2585,10 @@ var serveManyBase = ({
|
|
|
2536
2585
|
return new Response(
|
|
2537
2586
|
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
2538
2587
|
{
|
|
2539
|
-
status: 404
|
|
2588
|
+
status: 404,
|
|
2589
|
+
headers: {
|
|
2590
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
2591
|
+
}
|
|
2540
2592
|
}
|
|
2541
2593
|
);
|
|
2542
2594
|
}
|
|
@@ -2545,7 +2597,10 @@ var serveManyBase = ({
|
|
|
2545
2597
|
return new Response(
|
|
2546
2598
|
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
2547
2599
|
{
|
|
2548
|
-
status: 404
|
|
2600
|
+
status: 404,
|
|
2601
|
+
headers: {
|
|
2602
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
2603
|
+
}
|
|
2549
2604
|
}
|
|
2550
2605
|
);
|
|
2551
2606
|
}
|
|
@@ -2682,11 +2737,58 @@ var WorkflowContext = class {
|
|
|
2682
2737
|
* Number of retries
|
|
2683
2738
|
*/
|
|
2684
2739
|
retries;
|
|
2740
|
+
/**
|
|
2741
|
+
* Delay between retries.
|
|
2742
|
+
*
|
|
2743
|
+
* By default, the `retryDelay` is exponential backoff.
|
|
2744
|
+
* More details can be found in: https://upstash.com/docs/qstash/features/retry.
|
|
2745
|
+
*
|
|
2746
|
+
* The `retryDelay` option allows you to customize the delay (in milliseconds) between retry attempts when message delivery fails.
|
|
2747
|
+
*
|
|
2748
|
+
* You can use mathematical expressions and the following built-in functions to calculate the delay dynamically.
|
|
2749
|
+
* The special variable `retried` represents the current retry attempt count (starting from 0).
|
|
2750
|
+
*
|
|
2751
|
+
* Supported functions:
|
|
2752
|
+
* - `pow`
|
|
2753
|
+
* - `sqrt`
|
|
2754
|
+
* - `abs`
|
|
2755
|
+
* - `exp`
|
|
2756
|
+
* - `floor`
|
|
2757
|
+
* - `ceil`
|
|
2758
|
+
* - `round`
|
|
2759
|
+
* - `min`
|
|
2760
|
+
* - `max`
|
|
2761
|
+
*
|
|
2762
|
+
* Examples of valid `retryDelay` values:
|
|
2763
|
+
* ```ts
|
|
2764
|
+
* 1000 // 1 second
|
|
2765
|
+
* 1000 * (1 + retried) // 1 second multiplied by the current retry attempt
|
|
2766
|
+
* pow(2, retried) // 2 to the power of the current retry attempt
|
|
2767
|
+
* max(10, pow(2, retried)) // The greater of 10 or 2^retried
|
|
2768
|
+
* ```
|
|
2769
|
+
*/
|
|
2770
|
+
retryDelay;
|
|
2685
2771
|
/**
|
|
2686
2772
|
* Settings for controlling the number of active requests
|
|
2687
2773
|
* and number of requests per second with the same key.
|
|
2688
2774
|
*/
|
|
2689
2775
|
flowControl;
|
|
2776
|
+
/**
|
|
2777
|
+
* Label to apply to the workflow run.
|
|
2778
|
+
*
|
|
2779
|
+
* Can be used to filter the workflow run logs.
|
|
2780
|
+
*
|
|
2781
|
+
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2782
|
+
* with `client.trigger`:
|
|
2783
|
+
*
|
|
2784
|
+
* ```ts
|
|
2785
|
+
* await client.trigger({
|
|
2786
|
+
* url: "https://workflow-endpoint.com",
|
|
2787
|
+
* label: "my-label"
|
|
2788
|
+
* });
|
|
2789
|
+
* ```
|
|
2790
|
+
*/
|
|
2791
|
+
label;
|
|
2690
2792
|
constructor({
|
|
2691
2793
|
qstashClient,
|
|
2692
2794
|
workflowRunId,
|
|
@@ -2698,9 +2800,11 @@ var WorkflowContext = class {
|
|
|
2698
2800
|
initialPayload,
|
|
2699
2801
|
env,
|
|
2700
2802
|
retries,
|
|
2803
|
+
retryDelay,
|
|
2701
2804
|
telemetry: telemetry2,
|
|
2702
2805
|
invokeCount,
|
|
2703
|
-
flowControl
|
|
2806
|
+
flowControl,
|
|
2807
|
+
label
|
|
2704
2808
|
}) {
|
|
2705
2809
|
this.qstashClient = qstashClient;
|
|
2706
2810
|
this.workflowRunId = workflowRunId;
|
|
@@ -2711,7 +2815,9 @@ var WorkflowContext = class {
|
|
|
2711
2815
|
this.requestPayload = initialPayload;
|
|
2712
2816
|
this.env = env ?? {};
|
|
2713
2817
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2818
|
+
this.retryDelay = retryDelay;
|
|
2714
2819
|
this.flowControl = flowControl;
|
|
2820
|
+
this.label = label;
|
|
2715
2821
|
this.executor = new AutoExecutor(this, this.steps, telemetry2, invokeCount, debug);
|
|
2716
2822
|
}
|
|
2717
2823
|
/**
|
|
@@ -2792,6 +2898,7 @@ var WorkflowContext = class {
|
|
|
2792
2898
|
settings.body,
|
|
2793
2899
|
settings.headers || {},
|
|
2794
2900
|
settings.retries || 0,
|
|
2901
|
+
settings.retryDelay,
|
|
2795
2902
|
settings.timeout,
|
|
2796
2903
|
settings.flowControl ?? settings.workflow.options.flowControl
|
|
2797
2904
|
);
|
|
@@ -2802,6 +2909,7 @@ var WorkflowContext = class {
|
|
|
2802
2909
|
body,
|
|
2803
2910
|
headers = {},
|
|
2804
2911
|
retries = 0,
|
|
2912
|
+
retryDelay,
|
|
2805
2913
|
timeout,
|
|
2806
2914
|
flowControl
|
|
2807
2915
|
} = settings;
|
|
@@ -2812,6 +2920,7 @@ var WorkflowContext = class {
|
|
|
2812
2920
|
body,
|
|
2813
2921
|
headers,
|
|
2814
2922
|
retries,
|
|
2923
|
+
retryDelay,
|
|
2815
2924
|
timeout,
|
|
2816
2925
|
flowControl
|
|
2817
2926
|
);
|
|
@@ -2822,7 +2931,7 @@ var WorkflowContext = class {
|
|
|
2822
2931
|
* Pauses workflow execution until a specific event occurs or a timeout is reached.
|
|
2823
2932
|
*
|
|
2824
2933
|
*```ts
|
|
2825
|
-
* const result = await workflow.waitForEvent("payment-confirmed", {
|
|
2934
|
+
* const result = await workflow.waitForEvent("payment-confirmed", "payment.confirmed", {
|
|
2826
2935
|
* timeout: "5m"
|
|
2827
2936
|
* });
|
|
2828
2937
|
*```
|
|
@@ -2848,7 +2957,7 @@ var WorkflowContext = class {
|
|
|
2848
2957
|
* @param stepName
|
|
2849
2958
|
* @param eventId - Unique identifier for the event to wait for
|
|
2850
2959
|
* @param options - Configuration options.
|
|
2851
|
-
* @returns `{ timeout: boolean, eventData:
|
|
2960
|
+
* @returns `{ timeout: boolean, eventData: TEventData }`.
|
|
2852
2961
|
* The `timeout` property specifies if the workflow has timed out. The `eventData`
|
|
2853
2962
|
* is the data passed when notifying this workflow of an event.
|
|
2854
2963
|
*/
|
|
@@ -3008,7 +3117,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3008
3117
|
initialPayload: context.requestPayload,
|
|
3009
3118
|
env: context.env,
|
|
3010
3119
|
retries: context.retries,
|
|
3011
|
-
|
|
3120
|
+
retryDelay: context.retryDelay,
|
|
3121
|
+
flowControl: context.flowControl,
|
|
3122
|
+
label: context.label
|
|
3012
3123
|
});
|
|
3013
3124
|
try {
|
|
3014
3125
|
await routeFunction(disabledContext);
|
|
@@ -3016,6 +3127,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3016
3127
|
if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
|
|
3017
3128
|
return ok("step-found");
|
|
3018
3129
|
}
|
|
3130
|
+
console.warn(
|
|
3131
|
+
"Upstash Workflow: Received an error while authorizing request. Please avoid throwing errors before the first step of your workflow."
|
|
3132
|
+
);
|
|
3019
3133
|
return err(error);
|
|
3020
3134
|
}
|
|
3021
3135
|
return ok("run-ended");
|
|
@@ -3157,9 +3271,9 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
3157
3271
|
};
|
|
3158
3272
|
}
|
|
3159
3273
|
};
|
|
3160
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
3274
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, retryDelay, flowControl, debug) => {
|
|
3161
3275
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
3162
|
-
return ok("not-failure-callback");
|
|
3276
|
+
return ok({ result: "not-failure-callback" });
|
|
3163
3277
|
}
|
|
3164
3278
|
if (!failureFunction) {
|
|
3165
3279
|
return err(
|
|
@@ -3182,20 +3296,23 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3182
3296
|
if (!errorMessage) {
|
|
3183
3297
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3184
3298
|
}
|
|
3299
|
+
const userHeaders = recreateUserHeaders(request.headers);
|
|
3185
3300
|
const workflowContext = new WorkflowContext({
|
|
3186
3301
|
qstashClient,
|
|
3187
3302
|
workflowRunId,
|
|
3188
3303
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
3189
|
-
headers:
|
|
3304
|
+
headers: userHeaders,
|
|
3190
3305
|
steps: [],
|
|
3191
3306
|
url,
|
|
3192
3307
|
failureUrl: url,
|
|
3193
3308
|
debug,
|
|
3194
3309
|
env,
|
|
3195
3310
|
retries,
|
|
3311
|
+
retryDelay,
|
|
3196
3312
|
flowControl,
|
|
3197
|
-
telemetry: void 0
|
|
3313
|
+
telemetry: void 0,
|
|
3198
3314
|
// not going to make requests in authentication check
|
|
3315
|
+
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0
|
|
3199
3316
|
});
|
|
3200
3317
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3201
3318
|
routeFunction,
|
|
@@ -3207,16 +3324,16 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
3207
3324
|
} else if (authCheck.value === "run-ended") {
|
|
3208
3325
|
return err(new WorkflowError("Not authorized to run the failure function."));
|
|
3209
3326
|
}
|
|
3210
|
-
await failureFunction({
|
|
3327
|
+
const failureResponse = await failureFunction({
|
|
3211
3328
|
context: workflowContext,
|
|
3212
3329
|
failStatus: status,
|
|
3213
3330
|
failResponse: errorMessage,
|
|
3214
3331
|
failHeaders: header
|
|
3215
3332
|
});
|
|
3333
|
+
return ok({ result: "is-failure-callback", response: failureResponse });
|
|
3216
3334
|
} catch (error) {
|
|
3217
3335
|
return err(error);
|
|
3218
3336
|
}
|
|
3219
|
-
return ok("is-failure-callback");
|
|
3220
3337
|
};
|
|
3221
3338
|
|
|
3222
3339
|
// src/serve/options.ts
|
|
@@ -3232,8 +3349,8 @@ var processOptions = (options) => {
|
|
|
3232
3349
|
baseUrl: environment.QSTASH_URL,
|
|
3233
3350
|
token: environment.QSTASH_TOKEN
|
|
3234
3351
|
}),
|
|
3235
|
-
onStepFinish: (workflowRunId,
|
|
3236
|
-
if (
|
|
3352
|
+
onStepFinish: (workflowRunId, _finishCondition, detailedFinishCondition) => {
|
|
3353
|
+
if (detailedFinishCondition?.condition === "auth-fail") {
|
|
3237
3354
|
console.error(AUTH_FAIL_MESSAGE);
|
|
3238
3355
|
return new Response(
|
|
3239
3356
|
JSON.stringify({
|
|
@@ -3241,19 +3358,33 @@ var processOptions = (options) => {
|
|
|
3241
3358
|
workflowRunId
|
|
3242
3359
|
}),
|
|
3243
3360
|
{
|
|
3244
|
-
status: 400
|
|
3361
|
+
status: 400,
|
|
3362
|
+
headers: {
|
|
3363
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3364
|
+
}
|
|
3245
3365
|
}
|
|
3246
3366
|
);
|
|
3247
|
-
} else if (
|
|
3248
|
-
return new Response(JSON.stringify(formatWorkflowError(
|
|
3367
|
+
} else if (detailedFinishCondition?.condition === "non-retryable-error") {
|
|
3368
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3249
3369
|
headers: {
|
|
3250
|
-
"Upstash-NonRetryable-Error": "true"
|
|
3370
|
+
"Upstash-NonRetryable-Error": "true",
|
|
3371
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3251
3372
|
},
|
|
3252
3373
|
status: 489
|
|
3253
3374
|
});
|
|
3375
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3376
|
+
return new Response(detailedFinishCondition.result ?? void 0, {
|
|
3377
|
+
status: 200,
|
|
3378
|
+
headers: {
|
|
3379
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3380
|
+
}
|
|
3381
|
+
});
|
|
3254
3382
|
}
|
|
3255
3383
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3256
|
-
status: 200
|
|
3384
|
+
status: 200,
|
|
3385
|
+
headers: {
|
|
3386
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3387
|
+
}
|
|
3257
3388
|
});
|
|
3258
3389
|
},
|
|
3259
3390
|
initialPayloadParser: (initialRequest) => {
|
|
@@ -3327,6 +3458,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3327
3458
|
baseUrl,
|
|
3328
3459
|
env,
|
|
3329
3460
|
retries,
|
|
3461
|
+
retryDelay,
|
|
3330
3462
|
useJSONContent,
|
|
3331
3463
|
disableTelemetry,
|
|
3332
3464
|
flowControl,
|
|
@@ -3357,10 +3489,14 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3357
3489
|
debug
|
|
3358
3490
|
);
|
|
3359
3491
|
if (workflowRunEnded) {
|
|
3360
|
-
return onStepFinish(workflowRunId, "workflow-already-ended"
|
|
3492
|
+
return onStepFinish(workflowRunId, "workflow-already-ended", {
|
|
3493
|
+
condition: "workflow-already-ended"
|
|
3494
|
+
});
|
|
3361
3495
|
}
|
|
3362
3496
|
if (isLastDuplicate) {
|
|
3363
|
-
return onStepFinish(workflowRunId, "duplicate-step"
|
|
3497
|
+
return onStepFinish(workflowRunId, "duplicate-step", {
|
|
3498
|
+
condition: "duplicate-step"
|
|
3499
|
+
});
|
|
3364
3500
|
}
|
|
3365
3501
|
const failureCheck = await handleFailure(
|
|
3366
3502
|
request,
|
|
@@ -3371,16 +3507,21 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3371
3507
|
failureFunction,
|
|
3372
3508
|
env,
|
|
3373
3509
|
retries,
|
|
3510
|
+
retryDelay,
|
|
3374
3511
|
flowControl,
|
|
3375
3512
|
debug
|
|
3376
3513
|
);
|
|
3377
3514
|
if (failureCheck.isErr()) {
|
|
3378
3515
|
throw failureCheck.error;
|
|
3379
|
-
} else if (failureCheck.value === "is-failure-callback") {
|
|
3516
|
+
} else if (failureCheck.value.result === "is-failure-callback") {
|
|
3380
3517
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
3381
|
-
return onStepFinish(workflowRunId, "failure-callback"
|
|
3518
|
+
return onStepFinish(workflowRunId, "failure-callback", {
|
|
3519
|
+
condition: "failure-callback",
|
|
3520
|
+
result: failureCheck.value.response
|
|
3521
|
+
});
|
|
3382
3522
|
}
|
|
3383
3523
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3524
|
+
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3384
3525
|
const workflowContext = new WorkflowContext({
|
|
3385
3526
|
qstashClient,
|
|
3386
3527
|
workflowRunId,
|
|
@@ -3392,9 +3533,11 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3392
3533
|
debug,
|
|
3393
3534
|
env,
|
|
3394
3535
|
retries,
|
|
3536
|
+
retryDelay,
|
|
3395
3537
|
telemetry: telemetry2,
|
|
3396
3538
|
invokeCount,
|
|
3397
|
-
flowControl
|
|
3539
|
+
flowControl,
|
|
3540
|
+
label
|
|
3398
3541
|
});
|
|
3399
3542
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3400
3543
|
routeFunction,
|
|
@@ -3407,7 +3550,8 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3407
3550
|
await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
|
|
3408
3551
|
return onStepFinish(
|
|
3409
3552
|
isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
|
|
3410
|
-
"auth-fail"
|
|
3553
|
+
"auth-fail",
|
|
3554
|
+
{ condition: "auth-fail" }
|
|
3411
3555
|
);
|
|
3412
3556
|
}
|
|
3413
3557
|
const callReturnCheck = await handleThirdPartyCallResult({
|
|
@@ -3417,6 +3561,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3417
3561
|
workflowUrl,
|
|
3418
3562
|
failureUrl: workflowFailureUrl,
|
|
3419
3563
|
retries,
|
|
3564
|
+
retryDelay,
|
|
3420
3565
|
flowControl,
|
|
3421
3566
|
telemetry: telemetry2,
|
|
3422
3567
|
debug
|
|
@@ -3444,19 +3589,28 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3444
3589
|
debug
|
|
3445
3590
|
});
|
|
3446
3591
|
if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
|
|
3447
|
-
return onStepFinish(workflowRunId, result.value
|
|
3592
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
3593
|
+
condition: "non-retryable-error",
|
|
3594
|
+
result: result.value
|
|
3595
|
+
});
|
|
3448
3596
|
}
|
|
3449
3597
|
if (result.isErr()) {
|
|
3450
3598
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3451
3599
|
throw result.error;
|
|
3452
3600
|
}
|
|
3453
3601
|
await debug?.log("INFO", "RESPONSE_WORKFLOW");
|
|
3454
|
-
return onStepFinish(workflowContext.workflowRunId, "success"
|
|
3602
|
+
return onStepFinish(workflowContext.workflowRunId, "success", {
|
|
3603
|
+
condition: "success"
|
|
3604
|
+
});
|
|
3455
3605
|
} else if (callReturnCheck.value === "workflow-ended") {
|
|
3456
|
-
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended"
|
|
3606
|
+
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended", {
|
|
3607
|
+
condition: "workflow-already-ended"
|
|
3608
|
+
});
|
|
3457
3609
|
}
|
|
3458
3610
|
await debug?.log("INFO", "RESPONSE_DEFAULT");
|
|
3459
|
-
return onStepFinish("no-workflow-id", "fromCallback"
|
|
3611
|
+
return onStepFinish("no-workflow-id", "fromCallback", {
|
|
3612
|
+
condition: "fromCallback"
|
|
3613
|
+
});
|
|
3460
3614
|
};
|
|
3461
3615
|
const safeHandler = async (request) => {
|
|
3462
3616
|
try {
|
|
@@ -3471,11 +3625,17 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3471
3625
|
Original error: '${formattedError.message}'`;
|
|
3472
3626
|
console.error(errorMessage);
|
|
3473
3627
|
return new Response(errorMessage, {
|
|
3474
|
-
status: 500
|
|
3628
|
+
status: 500,
|
|
3629
|
+
headers: {
|
|
3630
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3631
|
+
}
|
|
3475
3632
|
});
|
|
3476
3633
|
}
|
|
3477
3634
|
return new Response(JSON.stringify(formattedError), {
|
|
3478
|
-
status: 500
|
|
3635
|
+
status: 500,
|
|
3636
|
+
headers: {
|
|
3637
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3638
|
+
}
|
|
3479
3639
|
});
|
|
3480
3640
|
}
|
|
3481
3641
|
};
|