@upstash/workflow 1.3.3 → 1.4.0
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.js +42 -5
- package/astro.mjs +3 -1
- package/{chunk-WEQGCISK.mjs → chunk-DRHEHWMS.mjs} +42 -5
- package/cloudflare.js +42 -5
- package/cloudflare.mjs +3 -1
- package/express.js +43 -5
- package/express.mjs +4 -1
- package/h3.js +42 -5
- package/h3.mjs +3 -1
- package/hono.js +42 -5
- package/hono.mjs +3 -1
- package/index.d.mts +22 -4
- package/index.d.ts +22 -4
- package/index.js +65 -7
- package/index.mjs +26 -3
- package/nextjs.js +43 -5
- package/nextjs.mjs +4 -1
- package/package.json +1 -1
- package/react-router.js +42 -5
- package/react-router.mjs +3 -1
- package/solidjs.js +42 -5
- package/solidjs.mjs +3 -1
- package/svelte.js +42 -5
- package/svelte.mjs +3 -1
- package/tanstack.js +42 -5
- package/tanstack.mjs +3 -1
package/astro.js
CHANGED
|
@@ -26,6 +26,9 @@ __export(astro_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(astro_exports);
|
|
28
28
|
|
|
29
|
+
// src/serve/index.ts
|
|
30
|
+
var import_qstash12 = require("@upstash/qstash");
|
|
31
|
+
|
|
29
32
|
// src/client/utils.ts
|
|
30
33
|
var import_qstash2 = require("@upstash/qstash");
|
|
31
34
|
|
|
@@ -781,6 +784,10 @@ var triggerFirstInvocation = async (params) => {
|
|
|
781
784
|
workflowConfig: {
|
|
782
785
|
workflowRunId: workflowContext.workflowRunId,
|
|
783
786
|
workflowUrl: workflowContext.url,
|
|
787
|
+
// the run doesn't exist yet, so the trigger time is sent when the creation time
|
|
788
|
+
// is not known. serve and client.trigger set it on the context already, so a
|
|
789
|
+
// retry of this request carries the same value and is deduplicated.
|
|
790
|
+
workflowRunCreatedAt: workflowContext.workflowRunCreatedAt || Date.now(),
|
|
784
791
|
failureUrl,
|
|
785
792
|
retries,
|
|
786
793
|
retryDelay,
|
|
@@ -884,7 +891,10 @@ var triggerWorkflowDelete = async (workflowContext, result, cancel = false, disp
|
|
|
884
891
|
path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
|
|
885
892
|
method: "DELETE",
|
|
886
893
|
parseResponseAsJson: false,
|
|
887
|
-
body: JSON.stringify(result)
|
|
894
|
+
body: JSON.stringify(result),
|
|
895
|
+
// with the creation time, QStash deletes the run only if it is the same run.
|
|
896
|
+
// a late delete of a previous run can't delete a new run with the same id.
|
|
897
|
+
headers: workflowContext.workflowRunCreatedAt ? { [WORKFLOW_CREATED_AT_HEADER]: workflowContext.workflowRunCreatedAt.toString() } : void 0
|
|
888
898
|
});
|
|
889
899
|
await dispatchDebug?.("onInfo", {
|
|
890
900
|
info: `Workflow run ${workflowContext.workflowRunId} deleted from QStash successfully.`
|
|
@@ -961,6 +971,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
961
971
|
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
962
972
|
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
963
973
|
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
974
|
+
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
964
975
|
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
965
976
|
throw new Error(
|
|
966
977
|
`Missing info in callback message source header: ${JSON.stringify({
|
|
@@ -978,6 +989,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
978
989
|
workflowConfig: {
|
|
979
990
|
workflowRunId,
|
|
980
991
|
workflowUrl,
|
|
992
|
+
workflowRunCreatedAt: Number(workflowRunCreatedAt ?? "0"),
|
|
981
993
|
telemetry: telemetry2
|
|
982
994
|
},
|
|
983
995
|
invokeCount: Number(invokeCount)
|
|
@@ -1125,6 +1137,7 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1125
1137
|
workflowConfig: {
|
|
1126
1138
|
workflowRunId: context.workflowRunId,
|
|
1127
1139
|
workflowUrl: context.url,
|
|
1140
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1128
1141
|
useJSONContent: false,
|
|
1129
1142
|
telemetry: telemetry2
|
|
1130
1143
|
},
|
|
@@ -1452,6 +1465,8 @@ var LazyWaitEventStep = class extends BaseLazyStep {
|
|
|
1452
1465
|
) : {},
|
|
1453
1466
|
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
1454
1467
|
"Upstash-Workflow-Runid": [context.workflowRunId],
|
|
1468
|
+
// same for WORKFLOW_CREATED_AT_HEADER, because Createdat -> CreatedAt:
|
|
1469
|
+
...context.workflowRunCreatedAt ? { "Upstash-Workflow-Createdat": [context.workflowRunCreatedAt.toString()] } : {},
|
|
1455
1470
|
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
1456
1471
|
[WORKFLOW_URL_HEADER]: [context.url],
|
|
1457
1472
|
"Upstash-Workflow-CallType": ["step"]
|
|
@@ -1554,6 +1569,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1554
1569
|
workflowConfig: {
|
|
1555
1570
|
workflowRunId: context.workflowRunId,
|
|
1556
1571
|
workflowUrl: context.url,
|
|
1572
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1557
1573
|
telemetry: telemetry2,
|
|
1558
1574
|
useJSONContent: false
|
|
1559
1575
|
},
|
|
@@ -1563,6 +1579,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1563
1579
|
invokerHeaders[key] = value;
|
|
1564
1580
|
});
|
|
1565
1581
|
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1582
|
+
if (context.workflowRunCreatedAt) {
|
|
1583
|
+
invokerHeaders["Upstash-Workflow-Createdat"] = context.workflowRunCreatedAt.toString();
|
|
1584
|
+
}
|
|
1566
1585
|
const request = {
|
|
1567
1586
|
body: stringifyBody(this.params.body),
|
|
1568
1587
|
headers: Object.fromEntries(
|
|
@@ -1591,6 +1610,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1591
1610
|
workflowConfig: {
|
|
1592
1611
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1593
1612
|
workflowUrl: newUrl,
|
|
1613
|
+
// the invoked run doesn't exist yet, so the creation time of the invoker run is sent.
|
|
1614
|
+
// it separates the invocations made by different runs of the invoker.
|
|
1615
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1594
1616
|
retries,
|
|
1595
1617
|
retryDelay,
|
|
1596
1618
|
telemetry: telemetry2,
|
|
@@ -1755,6 +1777,9 @@ var WorkflowHeaders = class {
|
|
|
1755
1777
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1756
1778
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {}
|
|
1757
1779
|
};
|
|
1780
|
+
if (this.workflowConfig.workflowRunCreatedAt) {
|
|
1781
|
+
this.headers.rawHeaders[WORKFLOW_CREATED_AT_HEADER] = this.workflowConfig.workflowRunCreatedAt.toString();
|
|
1782
|
+
}
|
|
1758
1783
|
if (this.stepInfo?.lazyStep.stepType !== "Call") {
|
|
1759
1784
|
this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1760
1785
|
}
|
|
@@ -1914,6 +1939,7 @@ var submitParallelSteps = async ({
|
|
|
1914
1939
|
workflowConfig: {
|
|
1915
1940
|
workflowRunId: context.workflowRunId,
|
|
1916
1941
|
workflowUrl: context.url,
|
|
1942
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1917
1943
|
telemetry: telemetry2
|
|
1918
1944
|
},
|
|
1919
1945
|
invokeCount
|
|
@@ -3415,7 +3441,13 @@ var createRegionalHandler = (environment, receiverConfig, region, clientOptions)
|
|
|
3415
3441
|
const client = new import_qstash11.Client({
|
|
3416
3442
|
...clientOptions,
|
|
3417
3443
|
baseUrl: clientEnv.QSTASH_URL,
|
|
3418
|
-
token: clientEnv.QSTASH_TOKEN
|
|
3444
|
+
token: clientEnv.QSTASH_TOKEN,
|
|
3445
|
+
// Mirror the receiver's dev-mode decision so a single QSTASH_DEV=true points
|
|
3446
|
+
// the client at the local dev server too. Without this the QStash Client
|
|
3447
|
+
// re-derives dev mode from its own process.env, which is blind to the
|
|
3448
|
+
// Cloudflare worker `env` binding that actually carries QSTASH_DEV there.
|
|
3449
|
+
// An explicit devMode in the user's client config still wins.
|
|
3450
|
+
devMode: clientOptions?.devMode ?? isQStashDevModeEnabled(environment)
|
|
3419
3451
|
});
|
|
3420
3452
|
const receiver = getReceiver(environment, receiverConfig, region);
|
|
3421
3453
|
return { client, receiver };
|
|
@@ -3465,7 +3497,9 @@ var getQStashHandlers = ({
|
|
|
3465
3497
|
client: qstashClientOption && "http" in qstashClientOption ? qstashClientOption : new import_qstash11.Client({
|
|
3466
3498
|
...qstashClientOption,
|
|
3467
3499
|
baseUrl: environment.QSTASH_URL,
|
|
3468
|
-
token: environment.QSTASH_TOKEN
|
|
3500
|
+
token: environment.QSTASH_TOKEN,
|
|
3501
|
+
// Mirror the receiver's dev-mode decision (see createRegionalHandler).
|
|
3502
|
+
devMode: qstashClientOption?.devMode ?? isQStashDevModeEnabled(environment)
|
|
3469
3503
|
}),
|
|
3470
3504
|
receiver: getReceiver(environment, receiverConfig)
|
|
3471
3505
|
}
|
|
@@ -3804,7 +3838,8 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3804
3838
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3805
3839
|
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3806
3840
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3807
|
-
const
|
|
3841
|
+
const workflowRunCreatedAtHeader = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
3842
|
+
const workflowRunCreatedAt = workflowRunCreatedAtHeader ? Number(workflowRunCreatedAtHeader) : isFirstInvocation ? Date.now() : 0;
|
|
3808
3843
|
const workflowContext = new WorkflowContext({
|
|
3809
3844
|
qstashClient: regionalClient,
|
|
3810
3845
|
workflowRunId,
|
|
@@ -3817,7 +3852,7 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3817
3852
|
invokeCount,
|
|
3818
3853
|
label,
|
|
3819
3854
|
retried,
|
|
3820
|
-
workflowRunCreatedAt
|
|
3855
|
+
workflowRunCreatedAt,
|
|
3821
3856
|
middlewareManager
|
|
3822
3857
|
});
|
|
3823
3858
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
@@ -3940,12 +3975,14 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3940
3975
|
};
|
|
3941
3976
|
|
|
3942
3977
|
// platforms/astro.ts
|
|
3978
|
+
var import_qstash13 = require("@upstash/qstash");
|
|
3943
3979
|
var telemetry = {
|
|
3944
3980
|
sdk: SDK_TELEMETRY,
|
|
3945
3981
|
framework: "astro",
|
|
3946
3982
|
runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
|
|
3947
3983
|
};
|
|
3948
3984
|
function serve(routeFunction, options) {
|
|
3985
|
+
void (0, import_qstash13.startDevServer)();
|
|
3949
3986
|
const POST = (apiContext) => {
|
|
3950
3987
|
const { handler } = serveBase(
|
|
3951
3988
|
(workflowContext) => routeFunction(workflowContext, apiContext),
|
package/astro.mjs
CHANGED
|
@@ -2,15 +2,17 @@ import {
|
|
|
2
2
|
SDK_TELEMETRY,
|
|
3
3
|
serveBase,
|
|
4
4
|
serveManyBase
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DRHEHWMS.mjs";
|
|
6
6
|
|
|
7
7
|
// platforms/astro.ts
|
|
8
|
+
import { startDevServer } from "@upstash/qstash";
|
|
8
9
|
var telemetry = {
|
|
9
10
|
sdk: SDK_TELEMETRY,
|
|
10
11
|
framework: "astro",
|
|
11
12
|
runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
|
|
12
13
|
};
|
|
13
14
|
function serve(routeFunction, options) {
|
|
15
|
+
void startDevServer();
|
|
14
16
|
const POST = (apiContext) => {
|
|
15
17
|
const { handler } = serveBase(
|
|
16
18
|
(workflowContext) => routeFunction(workflowContext, apiContext),
|
|
@@ -906,6 +906,10 @@ var triggerFirstInvocation = async (params) => {
|
|
|
906
906
|
workflowConfig: {
|
|
907
907
|
workflowRunId: workflowContext.workflowRunId,
|
|
908
908
|
workflowUrl: workflowContext.url,
|
|
909
|
+
// the run doesn't exist yet, so the trigger time is sent when the creation time
|
|
910
|
+
// is not known. serve and client.trigger set it on the context already, so a
|
|
911
|
+
// retry of this request carries the same value and is deduplicated.
|
|
912
|
+
workflowRunCreatedAt: workflowContext.workflowRunCreatedAt || Date.now(),
|
|
909
913
|
failureUrl,
|
|
910
914
|
retries,
|
|
911
915
|
retryDelay,
|
|
@@ -1009,7 +1013,10 @@ var triggerWorkflowDelete = async (workflowContext, result, cancel = false, disp
|
|
|
1009
1013
|
path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
|
|
1010
1014
|
method: "DELETE",
|
|
1011
1015
|
parseResponseAsJson: false,
|
|
1012
|
-
body: JSON.stringify(result)
|
|
1016
|
+
body: JSON.stringify(result),
|
|
1017
|
+
// with the creation time, QStash deletes the run only if it is the same run.
|
|
1018
|
+
// a late delete of a previous run can't delete a new run with the same id.
|
|
1019
|
+
headers: workflowContext.workflowRunCreatedAt ? { [WORKFLOW_CREATED_AT_HEADER]: workflowContext.workflowRunCreatedAt.toString() } : void 0
|
|
1013
1020
|
});
|
|
1014
1021
|
await dispatchDebug?.("onInfo", {
|
|
1015
1022
|
info: `Workflow run ${workflowContext.workflowRunId} deleted from QStash successfully.`
|
|
@@ -1086,6 +1093,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
1086
1093
|
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
1087
1094
|
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
1088
1095
|
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
1096
|
+
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
1089
1097
|
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
1090
1098
|
throw new Error(
|
|
1091
1099
|
`Missing info in callback message source header: ${JSON.stringify({
|
|
@@ -1103,6 +1111,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
1103
1111
|
workflowConfig: {
|
|
1104
1112
|
workflowRunId,
|
|
1105
1113
|
workflowUrl,
|
|
1114
|
+
workflowRunCreatedAt: Number(workflowRunCreatedAt ?? "0"),
|
|
1106
1115
|
telemetry
|
|
1107
1116
|
},
|
|
1108
1117
|
invokeCount: Number(invokeCount)
|
|
@@ -1250,6 +1259,7 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1250
1259
|
workflowConfig: {
|
|
1251
1260
|
workflowRunId: context.workflowRunId,
|
|
1252
1261
|
workflowUrl: context.url,
|
|
1262
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1253
1263
|
useJSONContent: false,
|
|
1254
1264
|
telemetry
|
|
1255
1265
|
},
|
|
@@ -1577,6 +1587,8 @@ var LazyWaitEventStep = class extends BaseLazyStep {
|
|
|
1577
1587
|
) : {},
|
|
1578
1588
|
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
1579
1589
|
"Upstash-Workflow-Runid": [context.workflowRunId],
|
|
1590
|
+
// same for WORKFLOW_CREATED_AT_HEADER, because Createdat -> CreatedAt:
|
|
1591
|
+
...context.workflowRunCreatedAt ? { "Upstash-Workflow-Createdat": [context.workflowRunCreatedAt.toString()] } : {},
|
|
1580
1592
|
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
1581
1593
|
[WORKFLOW_URL_HEADER]: [context.url],
|
|
1582
1594
|
"Upstash-Workflow-CallType": ["step"]
|
|
@@ -1679,6 +1691,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1679
1691
|
workflowConfig: {
|
|
1680
1692
|
workflowRunId: context.workflowRunId,
|
|
1681
1693
|
workflowUrl: context.url,
|
|
1694
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1682
1695
|
telemetry,
|
|
1683
1696
|
useJSONContent: false
|
|
1684
1697
|
},
|
|
@@ -1688,6 +1701,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1688
1701
|
invokerHeaders[key] = value;
|
|
1689
1702
|
});
|
|
1690
1703
|
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1704
|
+
if (context.workflowRunCreatedAt) {
|
|
1705
|
+
invokerHeaders["Upstash-Workflow-Createdat"] = context.workflowRunCreatedAt.toString();
|
|
1706
|
+
}
|
|
1691
1707
|
const request = {
|
|
1692
1708
|
body: stringifyBody(this.params.body),
|
|
1693
1709
|
headers: Object.fromEntries(
|
|
@@ -1716,6 +1732,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1716
1732
|
workflowConfig: {
|
|
1717
1733
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1718
1734
|
workflowUrl: newUrl,
|
|
1735
|
+
// the invoked run doesn't exist yet, so the creation time of the invoker run is sent.
|
|
1736
|
+
// it separates the invocations made by different runs of the invoker.
|
|
1737
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1719
1738
|
retries,
|
|
1720
1739
|
retryDelay,
|
|
1721
1740
|
telemetry,
|
|
@@ -1880,6 +1899,9 @@ var WorkflowHeaders = class {
|
|
|
1880
1899
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1881
1900
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {}
|
|
1882
1901
|
};
|
|
1902
|
+
if (this.workflowConfig.workflowRunCreatedAt) {
|
|
1903
|
+
this.headers.rawHeaders[WORKFLOW_CREATED_AT_HEADER] = this.workflowConfig.workflowRunCreatedAt.toString();
|
|
1904
|
+
}
|
|
1883
1905
|
if (this.stepInfo?.lazyStep.stepType !== "Call") {
|
|
1884
1906
|
this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1885
1907
|
}
|
|
@@ -2039,6 +2061,7 @@ var submitParallelSteps = async ({
|
|
|
2039
2061
|
workflowConfig: {
|
|
2040
2062
|
workflowRunId: context.workflowRunId,
|
|
2041
2063
|
workflowUrl: context.url,
|
|
2064
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
2042
2065
|
telemetry
|
|
2043
2066
|
},
|
|
2044
2067
|
invokeCount
|
|
@@ -3167,6 +3190,9 @@ var loggingMiddleware = new WorkflowMiddleware({
|
|
|
3167
3190
|
}
|
|
3168
3191
|
});
|
|
3169
3192
|
|
|
3193
|
+
// src/serve/index.ts
|
|
3194
|
+
import { startDevServer } from "@upstash/qstash";
|
|
3195
|
+
|
|
3170
3196
|
// src/serve/authorization.ts
|
|
3171
3197
|
import { Client as Client2 } from "@upstash/qstash";
|
|
3172
3198
|
var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
|
|
@@ -3539,7 +3565,13 @@ var createRegionalHandler = (environment, receiverConfig, region, clientOptions)
|
|
|
3539
3565
|
const client = new Client3({
|
|
3540
3566
|
...clientOptions,
|
|
3541
3567
|
baseUrl: clientEnv.QSTASH_URL,
|
|
3542
|
-
token: clientEnv.QSTASH_TOKEN
|
|
3568
|
+
token: clientEnv.QSTASH_TOKEN,
|
|
3569
|
+
// Mirror the receiver's dev-mode decision so a single QSTASH_DEV=true points
|
|
3570
|
+
// the client at the local dev server too. Without this the QStash Client
|
|
3571
|
+
// re-derives dev mode from its own process.env, which is blind to the
|
|
3572
|
+
// Cloudflare worker `env` binding that actually carries QSTASH_DEV there.
|
|
3573
|
+
// An explicit devMode in the user's client config still wins.
|
|
3574
|
+
devMode: clientOptions?.devMode ?? isQStashDevModeEnabled(environment)
|
|
3543
3575
|
});
|
|
3544
3576
|
const receiver = getReceiver(environment, receiverConfig, region);
|
|
3545
3577
|
return { client, receiver };
|
|
@@ -3589,7 +3621,9 @@ var getQStashHandlers = ({
|
|
|
3589
3621
|
client: qstashClientOption && "http" in qstashClientOption ? qstashClientOption : new Client3({
|
|
3590
3622
|
...qstashClientOption,
|
|
3591
3623
|
baseUrl: environment.QSTASH_URL,
|
|
3592
|
-
token: environment.QSTASH_TOKEN
|
|
3624
|
+
token: environment.QSTASH_TOKEN,
|
|
3625
|
+
// Mirror the receiver's dev-mode decision (see createRegionalHandler).
|
|
3626
|
+
devMode: qstashClientOption?.devMode ?? isQStashDevModeEnabled(environment)
|
|
3593
3627
|
}),
|
|
3594
3628
|
receiver: getReceiver(environment, receiverConfig)
|
|
3595
3629
|
}
|
|
@@ -3854,7 +3888,8 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3854
3888
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3855
3889
|
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3856
3890
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3857
|
-
const
|
|
3891
|
+
const workflowRunCreatedAtHeader = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
3892
|
+
const workflowRunCreatedAt = workflowRunCreatedAtHeader ? Number(workflowRunCreatedAtHeader) : isFirstInvocation ? Date.now() : 0;
|
|
3858
3893
|
const workflowContext = new WorkflowContext({
|
|
3859
3894
|
qstashClient: regionalClient,
|
|
3860
3895
|
workflowRunId,
|
|
@@ -3867,7 +3902,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3867
3902
|
invokeCount,
|
|
3868
3903
|
label,
|
|
3869
3904
|
retried,
|
|
3870
|
-
workflowRunCreatedAt
|
|
3905
|
+
workflowRunCreatedAt,
|
|
3871
3906
|
middlewareManager
|
|
3872
3907
|
});
|
|
3873
3908
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
@@ -3989,6 +4024,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3989
4024
|
return { handler: safeHandler };
|
|
3990
4025
|
};
|
|
3991
4026
|
var serve = (routeFunction, options) => {
|
|
4027
|
+
void startDevServer();
|
|
3992
4028
|
return serveBase(
|
|
3993
4029
|
routeFunction,
|
|
3994
4030
|
{
|
|
@@ -4004,6 +4040,7 @@ export {
|
|
|
4004
4040
|
WorkflowAbort,
|
|
4005
4041
|
WorkflowNonRetryableError,
|
|
4006
4042
|
WorkflowRetryAfterError,
|
|
4043
|
+
isInstanceOf,
|
|
4007
4044
|
assertNonEmptyId,
|
|
4008
4045
|
toNonEmptyIdArray,
|
|
4009
4046
|
makeNotifyRequest,
|
package/cloudflare.js
CHANGED
|
@@ -51,6 +51,9 @@ var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
|
51
51
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
52
52
|
var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
|
|
53
53
|
|
|
54
|
+
// src/serve/index.ts
|
|
55
|
+
var import_qstash12 = require("@upstash/qstash");
|
|
56
|
+
|
|
54
57
|
// src/client/utils.ts
|
|
55
58
|
var import_qstash2 = require("@upstash/qstash");
|
|
56
59
|
|
|
@@ -781,6 +784,10 @@ var triggerFirstInvocation = async (params) => {
|
|
|
781
784
|
workflowConfig: {
|
|
782
785
|
workflowRunId: workflowContext.workflowRunId,
|
|
783
786
|
workflowUrl: workflowContext.url,
|
|
787
|
+
// the run doesn't exist yet, so the trigger time is sent when the creation time
|
|
788
|
+
// is not known. serve and client.trigger set it on the context already, so a
|
|
789
|
+
// retry of this request carries the same value and is deduplicated.
|
|
790
|
+
workflowRunCreatedAt: workflowContext.workflowRunCreatedAt || Date.now(),
|
|
784
791
|
failureUrl,
|
|
785
792
|
retries,
|
|
786
793
|
retryDelay,
|
|
@@ -884,7 +891,10 @@ var triggerWorkflowDelete = async (workflowContext, result, cancel = false, disp
|
|
|
884
891
|
path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
|
|
885
892
|
method: "DELETE",
|
|
886
893
|
parseResponseAsJson: false,
|
|
887
|
-
body: JSON.stringify(result)
|
|
894
|
+
body: JSON.stringify(result),
|
|
895
|
+
// with the creation time, QStash deletes the run only if it is the same run.
|
|
896
|
+
// a late delete of a previous run can't delete a new run with the same id.
|
|
897
|
+
headers: workflowContext.workflowRunCreatedAt ? { [WORKFLOW_CREATED_AT_HEADER]: workflowContext.workflowRunCreatedAt.toString() } : void 0
|
|
888
898
|
});
|
|
889
899
|
await dispatchDebug?.("onInfo", {
|
|
890
900
|
info: `Workflow run ${workflowContext.workflowRunId} deleted from QStash successfully.`
|
|
@@ -961,6 +971,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
961
971
|
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
962
972
|
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
963
973
|
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
974
|
+
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
964
975
|
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
965
976
|
throw new Error(
|
|
966
977
|
`Missing info in callback message source header: ${JSON.stringify({
|
|
@@ -978,6 +989,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
978
989
|
workflowConfig: {
|
|
979
990
|
workflowRunId,
|
|
980
991
|
workflowUrl,
|
|
992
|
+
workflowRunCreatedAt: Number(workflowRunCreatedAt ?? "0"),
|
|
981
993
|
telemetry: telemetry2
|
|
982
994
|
},
|
|
983
995
|
invokeCount: Number(invokeCount)
|
|
@@ -1125,6 +1137,7 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1125
1137
|
workflowConfig: {
|
|
1126
1138
|
workflowRunId: context.workflowRunId,
|
|
1127
1139
|
workflowUrl: context.url,
|
|
1140
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1128
1141
|
useJSONContent: false,
|
|
1129
1142
|
telemetry: telemetry2
|
|
1130
1143
|
},
|
|
@@ -1452,6 +1465,8 @@ var LazyWaitEventStep = class extends BaseLazyStep {
|
|
|
1452
1465
|
) : {},
|
|
1453
1466
|
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
1454
1467
|
"Upstash-Workflow-Runid": [context.workflowRunId],
|
|
1468
|
+
// same for WORKFLOW_CREATED_AT_HEADER, because Createdat -> CreatedAt:
|
|
1469
|
+
...context.workflowRunCreatedAt ? { "Upstash-Workflow-Createdat": [context.workflowRunCreatedAt.toString()] } : {},
|
|
1455
1470
|
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
1456
1471
|
[WORKFLOW_URL_HEADER]: [context.url],
|
|
1457
1472
|
"Upstash-Workflow-CallType": ["step"]
|
|
@@ -1554,6 +1569,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1554
1569
|
workflowConfig: {
|
|
1555
1570
|
workflowRunId: context.workflowRunId,
|
|
1556
1571
|
workflowUrl: context.url,
|
|
1572
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1557
1573
|
telemetry: telemetry2,
|
|
1558
1574
|
useJSONContent: false
|
|
1559
1575
|
},
|
|
@@ -1563,6 +1579,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1563
1579
|
invokerHeaders[key] = value;
|
|
1564
1580
|
});
|
|
1565
1581
|
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1582
|
+
if (context.workflowRunCreatedAt) {
|
|
1583
|
+
invokerHeaders["Upstash-Workflow-Createdat"] = context.workflowRunCreatedAt.toString();
|
|
1584
|
+
}
|
|
1566
1585
|
const request = {
|
|
1567
1586
|
body: stringifyBody(this.params.body),
|
|
1568
1587
|
headers: Object.fromEntries(
|
|
@@ -1591,6 +1610,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1591
1610
|
workflowConfig: {
|
|
1592
1611
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
1593
1612
|
workflowUrl: newUrl,
|
|
1613
|
+
// the invoked run doesn't exist yet, so the creation time of the invoker run is sent.
|
|
1614
|
+
// it separates the invocations made by different runs of the invoker.
|
|
1615
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1594
1616
|
retries,
|
|
1595
1617
|
retryDelay,
|
|
1596
1618
|
telemetry: telemetry2,
|
|
@@ -1755,6 +1777,9 @@ var WorkflowHeaders = class {
|
|
|
1755
1777
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1756
1778
|
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {}
|
|
1757
1779
|
};
|
|
1780
|
+
if (this.workflowConfig.workflowRunCreatedAt) {
|
|
1781
|
+
this.headers.rawHeaders[WORKFLOW_CREATED_AT_HEADER] = this.workflowConfig.workflowRunCreatedAt.toString();
|
|
1782
|
+
}
|
|
1758
1783
|
if (this.stepInfo?.lazyStep.stepType !== "Call") {
|
|
1759
1784
|
this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1760
1785
|
}
|
|
@@ -1914,6 +1939,7 @@ var submitParallelSteps = async ({
|
|
|
1914
1939
|
workflowConfig: {
|
|
1915
1940
|
workflowRunId: context.workflowRunId,
|
|
1916
1941
|
workflowUrl: context.url,
|
|
1942
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1917
1943
|
telemetry: telemetry2
|
|
1918
1944
|
},
|
|
1919
1945
|
invokeCount
|
|
@@ -3415,7 +3441,13 @@ var createRegionalHandler = (environment, receiverConfig, region, clientOptions)
|
|
|
3415
3441
|
const client = new import_qstash11.Client({
|
|
3416
3442
|
...clientOptions,
|
|
3417
3443
|
baseUrl: clientEnv.QSTASH_URL,
|
|
3418
|
-
token: clientEnv.QSTASH_TOKEN
|
|
3444
|
+
token: clientEnv.QSTASH_TOKEN,
|
|
3445
|
+
// Mirror the receiver's dev-mode decision so a single QSTASH_DEV=true points
|
|
3446
|
+
// the client at the local dev server too. Without this the QStash Client
|
|
3447
|
+
// re-derives dev mode from its own process.env, which is blind to the
|
|
3448
|
+
// Cloudflare worker `env` binding that actually carries QSTASH_DEV there.
|
|
3449
|
+
// An explicit devMode in the user's client config still wins.
|
|
3450
|
+
devMode: clientOptions?.devMode ?? isQStashDevModeEnabled(environment)
|
|
3419
3451
|
});
|
|
3420
3452
|
const receiver = getReceiver(environment, receiverConfig, region);
|
|
3421
3453
|
return { client, receiver };
|
|
@@ -3465,7 +3497,9 @@ var getQStashHandlers = ({
|
|
|
3465
3497
|
client: qstashClientOption && "http" in qstashClientOption ? qstashClientOption : new import_qstash11.Client({
|
|
3466
3498
|
...qstashClientOption,
|
|
3467
3499
|
baseUrl: environment.QSTASH_URL,
|
|
3468
|
-
token: environment.QSTASH_TOKEN
|
|
3500
|
+
token: environment.QSTASH_TOKEN,
|
|
3501
|
+
// Mirror the receiver's dev-mode decision (see createRegionalHandler).
|
|
3502
|
+
devMode: qstashClientOption?.devMode ?? isQStashDevModeEnabled(environment)
|
|
3469
3503
|
}),
|
|
3470
3504
|
receiver: getReceiver(environment, receiverConfig)
|
|
3471
3505
|
}
|
|
@@ -3804,7 +3838,8 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3804
3838
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3805
3839
|
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3806
3840
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3807
|
-
const
|
|
3841
|
+
const workflowRunCreatedAtHeader = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
3842
|
+
const workflowRunCreatedAt = workflowRunCreatedAtHeader ? Number(workflowRunCreatedAtHeader) : isFirstInvocation ? Date.now() : 0;
|
|
3808
3843
|
const workflowContext = new WorkflowContext({
|
|
3809
3844
|
qstashClient: regionalClient,
|
|
3810
3845
|
workflowRunId,
|
|
@@ -3817,7 +3852,7 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3817
3852
|
invokeCount,
|
|
3818
3853
|
label,
|
|
3819
3854
|
retried,
|
|
3820
|
-
workflowRunCreatedAt
|
|
3855
|
+
workflowRunCreatedAt,
|
|
3821
3856
|
middlewareManager
|
|
3822
3857
|
});
|
|
3823
3858
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
@@ -3940,6 +3975,7 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3940
3975
|
};
|
|
3941
3976
|
|
|
3942
3977
|
// platforms/cloudflare.ts
|
|
3978
|
+
var import_qstash13 = require("@upstash/qstash");
|
|
3943
3979
|
var getArgs = (args) => {
|
|
3944
3980
|
if (!Array.isArray(args) || args.length === 0) {
|
|
3945
3981
|
throw new Error("No arguments passed to serve handler");
|
|
@@ -3963,6 +3999,7 @@ var telemetry = {
|
|
|
3963
3999
|
framework: "cloudflare"
|
|
3964
4000
|
};
|
|
3965
4001
|
var serve = (routeFunction, options) => {
|
|
4002
|
+
void (0, import_qstash13.startDevServer)();
|
|
3966
4003
|
const fetch = async (...args) => {
|
|
3967
4004
|
const { request, env } = getArgs(args);
|
|
3968
4005
|
const { handler: serveHandler } = serveBase(routeFunction, telemetry, {
|
package/cloudflare.mjs
CHANGED
|
@@ -2,9 +2,10 @@ import {
|
|
|
2
2
|
SDK_TELEMETRY,
|
|
3
3
|
serveBase,
|
|
4
4
|
serveManyBase
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DRHEHWMS.mjs";
|
|
6
6
|
|
|
7
7
|
// platforms/cloudflare.ts
|
|
8
|
+
import { startDevServer } from "@upstash/qstash";
|
|
8
9
|
var getArgs = (args) => {
|
|
9
10
|
if (!Array.isArray(args) || args.length === 0) {
|
|
10
11
|
throw new Error("No arguments passed to serve handler");
|
|
@@ -28,6 +29,7 @@ var telemetry = {
|
|
|
28
29
|
framework: "cloudflare"
|
|
29
30
|
};
|
|
30
31
|
var serve = (routeFunction, options) => {
|
|
32
|
+
void startDevServer();
|
|
31
33
|
const fetch = async (...args) => {
|
|
32
34
|
const { request, env } = getArgs(args);
|
|
33
35
|
const { handler: serveHandler } = serveBase(routeFunction, telemetry, {
|