@upstash/workflow 0.2.8-rc-invoke → 0.2.9
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 +4 -4
- package/astro.d.ts +4 -4
- package/astro.js +282 -135
- package/astro.mjs +17 -15
- package/{chunk-IWAW7GIG.mjs → chunk-IPXJZU3K.mjs} +851 -592
- package/cloudflare.d.mts +4 -4
- package/cloudflare.d.ts +4 -4
- package/cloudflare.js +278 -135
- package/cloudflare.mjs +13 -15
- package/express.d.mts +4 -4
- package/express.d.ts +4 -4
- package/express.js +281 -144
- package/express.mjs +16 -22
- package/h3.d.mts +4 -4
- package/h3.d.ts +4 -4
- package/h3.js +275 -135
- package/h3.mjs +10 -15
- package/hono.d.mts +4 -4
- package/hono.d.ts +4 -4
- package/hono.js +277 -134
- package/hono.mjs +12 -14
- package/index.d.mts +268 -5
- package/index.d.ts +268 -5
- package/index.js +297 -43
- package/index.mjs +60 -3
- package/nextjs.d.mts +6 -6
- package/nextjs.d.ts +6 -6
- package/nextjs.js +286 -143
- package/nextjs.mjs +21 -23
- package/package.json +1 -1
- package/serve-many-BVDpPsF-.d.mts +13 -0
- package/serve-many-e4zufyXN.d.ts +13 -0
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +207 -41
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +8 -9
- package/svelte.d.ts +8 -9
- package/svelte.js +278 -135
- package/svelte.mjs +13 -15
- package/{types-C7Y7WUQd.d.mts → types-CYhDXnf8.d.mts} +110 -18
- package/{types-C7Y7WUQd.d.ts → types-CYhDXnf8.d.ts} +110 -18
- package/chunk-LCZMBGEM.mjs +0 -95
- package/serve-many-BlBvXfBS.d.mts +0 -10
- package/serve-many-Dw-UUnH6.d.ts +0 -10
package/h3.js
CHANGED
|
@@ -397,6 +397,7 @@ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
|
|
|
397
397
|
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
|
+
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
400
401
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
401
402
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
402
403
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
@@ -578,8 +579,9 @@ var LazyCallStep = class extends BaseLazyStep {
|
|
|
578
579
|
headers;
|
|
579
580
|
retries;
|
|
580
581
|
timeout;
|
|
582
|
+
flowControl;
|
|
581
583
|
stepType = "Call";
|
|
582
|
-
constructor(stepName, url, method, body, headers, retries, timeout) {
|
|
584
|
+
constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
|
|
583
585
|
super(stepName);
|
|
584
586
|
this.url = url;
|
|
585
587
|
this.method = method;
|
|
@@ -587,6 +589,7 @@ var LazyCallStep = class extends BaseLazyStep {
|
|
|
587
589
|
this.headers = headers;
|
|
588
590
|
this.retries = retries;
|
|
589
591
|
this.timeout = timeout;
|
|
592
|
+
this.flowControl = flowControl;
|
|
590
593
|
}
|
|
591
594
|
getPlanStep(concurrent, targetStep) {
|
|
592
595
|
return {
|
|
@@ -657,14 +660,22 @@ var LazyNotifyStep = class extends LazyFunctionStep {
|
|
|
657
660
|
var LazyInvokeStep = class extends BaseLazyStep {
|
|
658
661
|
stepType = "Invoke";
|
|
659
662
|
params;
|
|
660
|
-
constructor(stepName, {
|
|
663
|
+
constructor(stepName, {
|
|
664
|
+
workflow,
|
|
665
|
+
body,
|
|
666
|
+
headers = {},
|
|
667
|
+
workflowRunId,
|
|
668
|
+
retries,
|
|
669
|
+
flowControl
|
|
670
|
+
}) {
|
|
661
671
|
super(stepName);
|
|
662
672
|
this.params = {
|
|
663
673
|
workflow,
|
|
664
674
|
body,
|
|
665
675
|
headers,
|
|
666
676
|
workflowRunId: getWorkflowRunId(workflowRunId),
|
|
667
|
-
retries
|
|
677
|
+
retries,
|
|
678
|
+
flowControl
|
|
668
679
|
};
|
|
669
680
|
}
|
|
670
681
|
getPlanStep(concurrent, targetStep) {
|
|
@@ -1123,7 +1134,8 @@ var triggerFirstInvocation = async ({
|
|
|
1123
1134
|
workflowContext,
|
|
1124
1135
|
useJSONContent,
|
|
1125
1136
|
telemetry: telemetry2,
|
|
1126
|
-
debug
|
|
1137
|
+
debug,
|
|
1138
|
+
invokeCount
|
|
1127
1139
|
}) => {
|
|
1128
1140
|
const { headers } = getHeaders({
|
|
1129
1141
|
initHeaderValue: "true",
|
|
@@ -1132,7 +1144,9 @@ var triggerFirstInvocation = async ({
|
|
|
1132
1144
|
userHeaders: workflowContext.headers,
|
|
1133
1145
|
failureUrl: workflowContext.failureUrl,
|
|
1134
1146
|
retries: workflowContext.retries,
|
|
1135
|
-
telemetry: telemetry2
|
|
1147
|
+
telemetry: telemetry2,
|
|
1148
|
+
invokeCount,
|
|
1149
|
+
flowControl: workflowContext.flowControl
|
|
1136
1150
|
});
|
|
1137
1151
|
if (workflowContext.headers.get("content-type")) {
|
|
1138
1152
|
headers["content-type"] = workflowContext.headers.get("content-type");
|
|
@@ -1238,6 +1252,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
1238
1252
|
failureUrl,
|
|
1239
1253
|
retries,
|
|
1240
1254
|
telemetry: telemetry2,
|
|
1255
|
+
flowControl,
|
|
1241
1256
|
debug
|
|
1242
1257
|
}) => {
|
|
1243
1258
|
try {
|
|
@@ -1285,6 +1300,7 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
1285
1300
|
const stepType = request.headers.get("Upstash-Workflow-StepType");
|
|
1286
1301
|
const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
|
|
1287
1302
|
const contentType = request.headers.get("Upstash-Workflow-ContentType");
|
|
1303
|
+
const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
|
|
1288
1304
|
if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
|
|
1289
1305
|
throw new Error(
|
|
1290
1306
|
`Missing info in callback message source header: ${JSON.stringify({
|
|
@@ -1305,7 +1321,9 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
1305
1321
|
userHeaders,
|
|
1306
1322
|
failureUrl,
|
|
1307
1323
|
retries,
|
|
1308
|
-
telemetry: telemetry2
|
|
1324
|
+
telemetry: telemetry2,
|
|
1325
|
+
invokeCount: Number(invokeCount),
|
|
1326
|
+
flowControl
|
|
1309
1327
|
});
|
|
1310
1328
|
const callResponse = {
|
|
1311
1329
|
status: callbackMessage.status,
|
|
@@ -1361,7 +1379,10 @@ var getHeaders = ({
|
|
|
1361
1379
|
step,
|
|
1362
1380
|
callRetries,
|
|
1363
1381
|
callTimeout,
|
|
1364
|
-
telemetry: telemetry2
|
|
1382
|
+
telemetry: telemetry2,
|
|
1383
|
+
invokeCount,
|
|
1384
|
+
flowControl,
|
|
1385
|
+
callFlowControl
|
|
1365
1386
|
}) => {
|
|
1366
1387
|
const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
1367
1388
|
const baseHeaders = {
|
|
@@ -1373,6 +1394,9 @@ var getHeaders = ({
|
|
|
1373
1394
|
"content-type": contentType,
|
|
1374
1395
|
...telemetry2 ? getTelemetryHeaders(telemetry2) : {}
|
|
1375
1396
|
};
|
|
1397
|
+
if (invokeCount !== void 0 && !step?.callUrl) {
|
|
1398
|
+
baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
|
|
1399
|
+
}
|
|
1376
1400
|
if (!step?.callUrl) {
|
|
1377
1401
|
baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1378
1402
|
}
|
|
@@ -1381,13 +1405,23 @@ var getHeaders = ({
|
|
|
1381
1405
|
}
|
|
1382
1406
|
if (failureUrl) {
|
|
1383
1407
|
baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
|
|
1408
|
+
baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
|
|
1409
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
|
|
1410
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
|
|
1411
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
|
|
1412
|
+
baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
|
|
1413
|
+
if (retries !== void 0) {
|
|
1414
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1415
|
+
}
|
|
1416
|
+
if (flowControl) {
|
|
1417
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1418
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
|
|
1419
|
+
baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
|
|
1420
|
+
}
|
|
1384
1421
|
if (!step?.callUrl) {
|
|
1385
1422
|
baseHeaders["Upstash-Failure-Callback"] = failureUrl;
|
|
1386
1423
|
}
|
|
1387
1424
|
}
|
|
1388
|
-
if (step?.stepType === "Invoke") {
|
|
1389
|
-
baseHeaders["upstash-workflow-invoke"] = "true";
|
|
1390
|
-
}
|
|
1391
1425
|
if (step?.callUrl) {
|
|
1392
1426
|
baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
|
|
1393
1427
|
baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
@@ -1395,9 +1429,26 @@ var getHeaders = ({
|
|
|
1395
1429
|
baseHeaders["Upstash-Callback-Retries"] = retries.toString();
|
|
1396
1430
|
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1397
1431
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1432
|
+
if (callFlowControl) {
|
|
1433
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
|
|
1434
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1435
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1436
|
+
}
|
|
1437
|
+
if (flowControl) {
|
|
1438
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1439
|
+
baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
|
|
1440
|
+
baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
|
|
1441
|
+
}
|
|
1442
|
+
} else {
|
|
1443
|
+
if (flowControl) {
|
|
1444
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
1445
|
+
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1446
|
+
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1447
|
+
}
|
|
1448
|
+
if (retries !== void 0) {
|
|
1449
|
+
baseHeaders["Upstash-Retries"] = retries.toString();
|
|
1450
|
+
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
1451
|
+
}
|
|
1401
1452
|
}
|
|
1402
1453
|
if (userHeaders) {
|
|
1403
1454
|
for (const header of userHeaders.keys()) {
|
|
@@ -1432,6 +1483,7 @@ var getHeaders = ({
|
|
|
1432
1483
|
"Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
|
|
1433
1484
|
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
1434
1485
|
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
1486
|
+
[`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
|
|
1435
1487
|
"Upstash-Workflow-CallType": "toCallback"
|
|
1436
1488
|
}
|
|
1437
1489
|
};
|
|
@@ -1489,9 +1541,159 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
|
|
|
1489
1541
|
);
|
|
1490
1542
|
}
|
|
1491
1543
|
};
|
|
1544
|
+
var prepareFlowControl = (flowControl) => {
|
|
1545
|
+
const parallelism = flowControl.parallelism?.toString();
|
|
1546
|
+
const rate = flowControl.ratePerSecond?.toString();
|
|
1547
|
+
const controlValue = [
|
|
1548
|
+
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
1549
|
+
rate ? `rate=${rate}` : void 0
|
|
1550
|
+
].filter(Boolean);
|
|
1551
|
+
if (controlValue.length === 0) {
|
|
1552
|
+
throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
1553
|
+
}
|
|
1554
|
+
return {
|
|
1555
|
+
flowControlKey: flowControl.key,
|
|
1556
|
+
flowControlValue: controlValue.join(", ")
|
|
1557
|
+
};
|
|
1558
|
+
};
|
|
1492
1559
|
|
|
1493
1560
|
// src/context/auto-executor.ts
|
|
1494
1561
|
var import_qstash4 = require("@upstash/qstash");
|
|
1562
|
+
|
|
1563
|
+
// src/serve/serve-many.ts
|
|
1564
|
+
var getWorkflowId = (url) => {
|
|
1565
|
+
const components = url.split("/");
|
|
1566
|
+
const lastComponent = components[components.length - 1];
|
|
1567
|
+
return lastComponent.split("?")[0];
|
|
1568
|
+
};
|
|
1569
|
+
var serveManyBase = ({
|
|
1570
|
+
workflows,
|
|
1571
|
+
getUrl: getUrl2,
|
|
1572
|
+
serveMethod,
|
|
1573
|
+
options
|
|
1574
|
+
}) => {
|
|
1575
|
+
const workflowIds = [];
|
|
1576
|
+
const workflowMap = Object.fromEntries(
|
|
1577
|
+
Object.entries(workflows).map((workflow) => {
|
|
1578
|
+
const workflowId = workflow[0];
|
|
1579
|
+
if (workflowIds.includes(workflowId)) {
|
|
1580
|
+
throw new WorkflowError(
|
|
1581
|
+
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
if (workflowId.includes("/")) {
|
|
1585
|
+
throw new WorkflowError(
|
|
1586
|
+
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1589
|
+
workflowIds.push(workflowId);
|
|
1590
|
+
workflow[1].workflowId = workflowId;
|
|
1591
|
+
workflow[1].options = {
|
|
1592
|
+
...options,
|
|
1593
|
+
...workflow[1].options
|
|
1594
|
+
};
|
|
1595
|
+
const params = [workflow[1].routeFunction, workflow[1].options];
|
|
1596
|
+
const handler = serveMethod(...params);
|
|
1597
|
+
return [workflowId, handler];
|
|
1598
|
+
})
|
|
1599
|
+
);
|
|
1600
|
+
return {
|
|
1601
|
+
handler: async (...params) => {
|
|
1602
|
+
const url = getUrl2(...params);
|
|
1603
|
+
const pickedWorkflowId = getWorkflowId(url);
|
|
1604
|
+
if (!pickedWorkflowId) {
|
|
1605
|
+
return new Response(
|
|
1606
|
+
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
1607
|
+
{
|
|
1608
|
+
status: 404
|
|
1609
|
+
}
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
const workflow = workflowMap[pickedWorkflowId];
|
|
1613
|
+
if (!workflow) {
|
|
1614
|
+
return new Response(
|
|
1615
|
+
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
1616
|
+
{
|
|
1617
|
+
status: 404
|
|
1618
|
+
}
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
return await workflow(...params);
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
};
|
|
1625
|
+
var invokeWorkflow = async ({
|
|
1626
|
+
settings,
|
|
1627
|
+
invokeStep,
|
|
1628
|
+
context,
|
|
1629
|
+
invokeCount,
|
|
1630
|
+
telemetry: telemetry2
|
|
1631
|
+
}) => {
|
|
1632
|
+
const {
|
|
1633
|
+
body,
|
|
1634
|
+
workflow,
|
|
1635
|
+
headers = {},
|
|
1636
|
+
workflowRunId = getWorkflowRunId(),
|
|
1637
|
+
retries,
|
|
1638
|
+
flowControl
|
|
1639
|
+
} = settings;
|
|
1640
|
+
const { workflowId } = workflow;
|
|
1641
|
+
const {
|
|
1642
|
+
retries: workflowRetries,
|
|
1643
|
+
failureFunction,
|
|
1644
|
+
failureUrl,
|
|
1645
|
+
useJSONContent,
|
|
1646
|
+
flowControl: workflowFlowControl
|
|
1647
|
+
} = workflow.options;
|
|
1648
|
+
if (!workflowId) {
|
|
1649
|
+
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
1650
|
+
}
|
|
1651
|
+
const { headers: invokerHeaders } = getHeaders({
|
|
1652
|
+
initHeaderValue: "false",
|
|
1653
|
+
workflowRunId: context.workflowRunId,
|
|
1654
|
+
workflowUrl: context.url,
|
|
1655
|
+
userHeaders: context.headers,
|
|
1656
|
+
failureUrl: context.failureUrl,
|
|
1657
|
+
retries: context.retries,
|
|
1658
|
+
telemetry: telemetry2,
|
|
1659
|
+
invokeCount,
|
|
1660
|
+
flowControl: context.flowControl
|
|
1661
|
+
});
|
|
1662
|
+
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1663
|
+
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
1664
|
+
const { headers: triggerHeaders } = getHeaders({
|
|
1665
|
+
initHeaderValue: "true",
|
|
1666
|
+
workflowRunId,
|
|
1667
|
+
workflowUrl: newUrl,
|
|
1668
|
+
userHeaders: new Headers(headers),
|
|
1669
|
+
retries: retries ?? workflowRetries,
|
|
1670
|
+
telemetry: telemetry2,
|
|
1671
|
+
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1672
|
+
invokeCount: invokeCount + 1,
|
|
1673
|
+
flowControl: flowControl ?? workflowFlowControl
|
|
1674
|
+
});
|
|
1675
|
+
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1676
|
+
if (useJSONContent) {
|
|
1677
|
+
triggerHeaders["content-type"] = "application/json";
|
|
1678
|
+
}
|
|
1679
|
+
const request = {
|
|
1680
|
+
body: JSON.stringify(body),
|
|
1681
|
+
headers: Object.fromEntries(
|
|
1682
|
+
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1683
|
+
),
|
|
1684
|
+
workflowRunId,
|
|
1685
|
+
workflowUrl: context.url,
|
|
1686
|
+
step: invokeStep
|
|
1687
|
+
};
|
|
1688
|
+
await context.qstashClient.publish({
|
|
1689
|
+
headers: triggerHeaders,
|
|
1690
|
+
method: "POST",
|
|
1691
|
+
body: JSON.stringify(request),
|
|
1692
|
+
url: newUrl
|
|
1693
|
+
});
|
|
1694
|
+
};
|
|
1695
|
+
|
|
1696
|
+
// src/context/auto-executor.ts
|
|
1495
1697
|
var AutoExecutor = class _AutoExecutor {
|
|
1496
1698
|
context;
|
|
1497
1699
|
promises = /* @__PURE__ */ new WeakMap();
|
|
@@ -1500,14 +1702,16 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1500
1702
|
nonPlanStepCount;
|
|
1501
1703
|
steps;
|
|
1502
1704
|
indexInCurrentList = 0;
|
|
1705
|
+
invokeCount;
|
|
1503
1706
|
telemetry;
|
|
1504
1707
|
stepCount = 0;
|
|
1505
1708
|
planStepCount = 0;
|
|
1506
1709
|
executingStep = false;
|
|
1507
|
-
constructor(context, steps, telemetry2, debug) {
|
|
1710
|
+
constructor(context, steps, telemetry2, invokeCount, debug) {
|
|
1508
1711
|
this.context = context;
|
|
1509
1712
|
this.steps = steps;
|
|
1510
1713
|
this.telemetry = telemetry2;
|
|
1714
|
+
this.invokeCount = invokeCount ?? 0;
|
|
1511
1715
|
this.debug = debug;
|
|
1512
1716
|
this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
|
|
1513
1717
|
}
|
|
@@ -1730,7 +1934,9 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1730
1934
|
step: waitStep,
|
|
1731
1935
|
failureUrl: this.context.failureUrl,
|
|
1732
1936
|
retries: this.context.retries,
|
|
1733
|
-
telemetry: this.telemetry
|
|
1937
|
+
telemetry: this.telemetry,
|
|
1938
|
+
invokeCount: this.invokeCount,
|
|
1939
|
+
flowControl: this.context.flowControl
|
|
1734
1940
|
});
|
|
1735
1941
|
const waitBody = {
|
|
1736
1942
|
url: this.context.url,
|
|
@@ -1758,17 +1964,13 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1758
1964
|
if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
|
|
1759
1965
|
const invokeStep = steps[0];
|
|
1760
1966
|
const lazyInvokeStep = lazySteps[0];
|
|
1761
|
-
await
|
|
1762
|
-
|
|
1763
|
-
body: lazyInvokeStep.params.body,
|
|
1764
|
-
headers: lazyInvokeStep.params.headers,
|
|
1765
|
-
workflowRunId: lazyInvokeStep.params.workflowRunId,
|
|
1766
|
-
workflow: lazyInvokeStep.params.workflow,
|
|
1767
|
-
retries: lazyInvokeStep.params.retries
|
|
1768
|
-
},
|
|
1967
|
+
await invokeWorkflow({
|
|
1968
|
+
settings: lazyInvokeStep.params,
|
|
1769
1969
|
invokeStep,
|
|
1770
|
-
this.context
|
|
1771
|
-
|
|
1970
|
+
context: this.context,
|
|
1971
|
+
invokeCount: this.invokeCount,
|
|
1972
|
+
telemetry: this.telemetry
|
|
1973
|
+
});
|
|
1772
1974
|
throw new WorkflowAbort(invokeStep.stepName, invokeStep);
|
|
1773
1975
|
}
|
|
1774
1976
|
const result = await this.context.qstashClient.batchJSON(
|
|
@@ -1784,11 +1986,14 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1784
1986
|
retries: this.context.retries,
|
|
1785
1987
|
callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
|
|
1786
1988
|
callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
|
|
1787
|
-
telemetry: this.telemetry
|
|
1989
|
+
telemetry: this.telemetry,
|
|
1990
|
+
invokeCount: this.invokeCount,
|
|
1991
|
+
flowControl: this.context.flowControl,
|
|
1992
|
+
callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
|
|
1788
1993
|
});
|
|
1789
1994
|
const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
|
|
1790
1995
|
singleStep.out = JSON.stringify(singleStep.out);
|
|
1791
|
-
return singleStep.callUrl ? (
|
|
1996
|
+
return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
|
|
1792
1997
|
// if the step is a third party call, we call the third party
|
|
1793
1998
|
// url (singleStep.callUrl) and pass information about the workflow
|
|
1794
1999
|
// in the headers (handled in getHeaders). QStash makes the request
|
|
@@ -2088,9 +2293,10 @@ var wrapTools = ({
|
|
|
2088
2293
|
return Object.fromEntries(
|
|
2089
2294
|
Object.entries(tools).map((toolInfo) => {
|
|
2090
2295
|
const [toolName, tool3] = toolInfo;
|
|
2296
|
+
const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
|
|
2091
2297
|
const aiSDKTool = convertToAISDKTool(tool3);
|
|
2092
2298
|
const execute = aiSDKTool.execute;
|
|
2093
|
-
if (execute) {
|
|
2299
|
+
if (execute && executeAsStep) {
|
|
2094
2300
|
const wrappedExecute = (...params) => {
|
|
2095
2301
|
return context.run(`Run tool ${toolName}`, () => execute(...params));
|
|
2096
2302
|
};
|
|
@@ -2444,6 +2650,11 @@ var WorkflowContext = class {
|
|
|
2444
2650
|
* Number of retries
|
|
2445
2651
|
*/
|
|
2446
2652
|
retries;
|
|
2653
|
+
/**
|
|
2654
|
+
* Settings for controlling the number of active requests
|
|
2655
|
+
* and number of requests per second with the same key.
|
|
2656
|
+
*/
|
|
2657
|
+
flowControl;
|
|
2447
2658
|
constructor({
|
|
2448
2659
|
qstashClient,
|
|
2449
2660
|
workflowRunId,
|
|
@@ -2455,7 +2666,9 @@ var WorkflowContext = class {
|
|
|
2455
2666
|
initialPayload,
|
|
2456
2667
|
env,
|
|
2457
2668
|
retries,
|
|
2458
|
-
telemetry: telemetry2
|
|
2669
|
+
telemetry: telemetry2,
|
|
2670
|
+
invokeCount,
|
|
2671
|
+
flowControl
|
|
2459
2672
|
}) {
|
|
2460
2673
|
this.qstashClient = qstashClient;
|
|
2461
2674
|
this.workflowRunId = workflowRunId;
|
|
@@ -2466,7 +2679,8 @@ var WorkflowContext = class {
|
|
|
2466
2679
|
this.requestPayload = initialPayload;
|
|
2467
2680
|
this.env = env ?? {};
|
|
2468
2681
|
this.retries = retries ?? DEFAULT_RETRIES;
|
|
2469
|
-
this.
|
|
2682
|
+
this.flowControl = flowControl;
|
|
2683
|
+
this.executor = new AutoExecutor(this, this.steps, telemetry2, invokeCount, debug);
|
|
2470
2684
|
}
|
|
2471
2685
|
/**
|
|
2472
2686
|
* Executes a workflow step
|
|
@@ -2568,7 +2782,7 @@ var WorkflowContext = class {
|
|
|
2568
2782
|
* }
|
|
2569
2783
|
*/
|
|
2570
2784
|
async call(stepName, settings) {
|
|
2571
|
-
const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
|
|
2785
|
+
const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
|
|
2572
2786
|
const result = await this.addStep(
|
|
2573
2787
|
new LazyCallStep(
|
|
2574
2788
|
stepName,
|
|
@@ -2577,7 +2791,8 @@ var WorkflowContext = class {
|
|
|
2577
2791
|
body,
|
|
2578
2792
|
headers,
|
|
2579
2793
|
retries,
|
|
2580
|
-
timeout
|
|
2794
|
+
timeout,
|
|
2795
|
+
flowControl
|
|
2581
2796
|
)
|
|
2582
2797
|
);
|
|
2583
2798
|
if (typeof result === "string") {
|
|
@@ -2814,7 +3029,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2814
3029
|
failureUrl: context.failureUrl,
|
|
2815
3030
|
initialPayload: context.requestPayload,
|
|
2816
3031
|
env: context.env,
|
|
2817
|
-
retries: context.retries
|
|
3032
|
+
retries: context.retries,
|
|
3033
|
+
flowControl: context.flowControl
|
|
2818
3034
|
});
|
|
2819
3035
|
try {
|
|
2820
3036
|
await routeFunction(disabledContext);
|
|
@@ -2967,7 +3183,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2967
3183
|
};
|
|
2968
3184
|
}
|
|
2969
3185
|
};
|
|
2970
|
-
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
|
|
3186
|
+
var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
|
|
2971
3187
|
if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
|
|
2972
3188
|
return ok("not-failure-callback");
|
|
2973
3189
|
}
|
|
@@ -2979,22 +3195,21 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
2979
3195
|
);
|
|
2980
3196
|
}
|
|
2981
3197
|
try {
|
|
2982
|
-
const { status, header, body, url,
|
|
2983
|
-
requestPayload
|
|
2984
|
-
);
|
|
3198
|
+
const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
|
|
2985
3199
|
const decodedBody = body ? decodeBase64(body) : "{}";
|
|
2986
3200
|
const errorPayload = JSON.parse(decodedBody);
|
|
2987
3201
|
const workflowContext = new WorkflowContext({
|
|
2988
3202
|
qstashClient,
|
|
2989
3203
|
workflowRunId,
|
|
2990
3204
|
initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
|
|
2991
|
-
headers: recreateUserHeaders(
|
|
3205
|
+
headers: recreateUserHeaders(request.headers),
|
|
2992
3206
|
steps: [],
|
|
2993
3207
|
url,
|
|
2994
3208
|
failureUrl: url,
|
|
2995
3209
|
debug,
|
|
2996
3210
|
env,
|
|
2997
3211
|
retries,
|
|
3212
|
+
flowControl,
|
|
2998
3213
|
telemetry: void 0
|
|
2999
3214
|
// not going to make requests in authentication check
|
|
3000
3215
|
});
|
|
@@ -3121,7 +3336,8 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3121
3336
|
env,
|
|
3122
3337
|
retries,
|
|
3123
3338
|
useJSONContent,
|
|
3124
|
-
disableTelemetry
|
|
3339
|
+
disableTelemetry,
|
|
3340
|
+
flowControl
|
|
3125
3341
|
} = processOptions(options);
|
|
3126
3342
|
telemetry2 = disableTelemetry ? void 0 : telemetry2;
|
|
3127
3343
|
const debug = WorkflowLogger.getLogger(verbose);
|
|
@@ -3162,6 +3378,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3162
3378
|
failureFunction,
|
|
3163
3379
|
env,
|
|
3164
3380
|
retries,
|
|
3381
|
+
flowControl,
|
|
3165
3382
|
debug
|
|
3166
3383
|
);
|
|
3167
3384
|
if (failureCheck.isErr()) {
|
|
@@ -3170,6 +3387,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3170
3387
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
3171
3388
|
return onStepFinish(workflowRunId, "failure-callback");
|
|
3172
3389
|
}
|
|
3390
|
+
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3173
3391
|
const workflowContext = new WorkflowContext({
|
|
3174
3392
|
qstashClient,
|
|
3175
3393
|
workflowRunId,
|
|
@@ -3181,7 +3399,9 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3181
3399
|
debug,
|
|
3182
3400
|
env,
|
|
3183
3401
|
retries,
|
|
3184
|
-
telemetry: telemetry2
|
|
3402
|
+
telemetry: telemetry2,
|
|
3403
|
+
invokeCount,
|
|
3404
|
+
flowControl
|
|
3185
3405
|
});
|
|
3186
3406
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
3187
3407
|
routeFunction,
|
|
@@ -3204,6 +3424,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3204
3424
|
workflowUrl,
|
|
3205
3425
|
failureUrl: workflowFailureUrl,
|
|
3206
3426
|
retries,
|
|
3427
|
+
flowControl,
|
|
3207
3428
|
telemetry: telemetry2,
|
|
3208
3429
|
debug
|
|
3209
3430
|
});
|
|
@@ -3213,7 +3434,13 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3213
3434
|
});
|
|
3214
3435
|
throw callReturnCheck.error;
|
|
3215
3436
|
} else if (callReturnCheck.value === "continue-workflow") {
|
|
3216
|
-
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3437
|
+
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3438
|
+
workflowContext,
|
|
3439
|
+
useJSONContent,
|
|
3440
|
+
telemetry: telemetry2,
|
|
3441
|
+
debug,
|
|
3442
|
+
invokeCount
|
|
3443
|
+
}) : await triggerRouteFunction({
|
|
3217
3444
|
onStep: async () => routeFunction(workflowContext),
|
|
3218
3445
|
onCleanup: async (result2) => {
|
|
3219
3446
|
await triggerWorkflowDelete(workflowContext, result2, debug);
|
|
@@ -3248,91 +3475,6 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3248
3475
|
return { handler: safeHandler };
|
|
3249
3476
|
};
|
|
3250
3477
|
|
|
3251
|
-
// src/serve/serve-many.ts
|
|
3252
|
-
var serveManyBase = ({
|
|
3253
|
-
workflows,
|
|
3254
|
-
getWorkflowId
|
|
3255
|
-
}) => {
|
|
3256
|
-
const workflowIds = [];
|
|
3257
|
-
const workflowMap = Object.fromEntries(
|
|
3258
|
-
Object.entries(workflows).map((workflow) => {
|
|
3259
|
-
const workflowId = workflow[0];
|
|
3260
|
-
if (workflowIds.includes(workflowId)) {
|
|
3261
|
-
throw new WorkflowError(
|
|
3262
|
-
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
3263
|
-
);
|
|
3264
|
-
}
|
|
3265
|
-
if (workflowId.includes("/")) {
|
|
3266
|
-
throw new WorkflowError(
|
|
3267
|
-
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
3268
|
-
);
|
|
3269
|
-
}
|
|
3270
|
-
workflowIds.push(workflowId);
|
|
3271
|
-
workflow[1].workflowId = workflowId;
|
|
3272
|
-
return [workflowId, workflow[1].handler];
|
|
3273
|
-
})
|
|
3274
|
-
);
|
|
3275
|
-
return {
|
|
3276
|
-
handler: async (...params) => {
|
|
3277
|
-
const pickedWorkflowId = getWorkflowId(...params);
|
|
3278
|
-
if (!pickedWorkflowId) {
|
|
3279
|
-
throw new WorkflowError(`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`);
|
|
3280
|
-
}
|
|
3281
|
-
const workflow = workflowMap[pickedWorkflowId];
|
|
3282
|
-
if (!workflow) {
|
|
3283
|
-
throw new WorkflowError(`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`);
|
|
3284
|
-
}
|
|
3285
|
-
return await workflow(...params);
|
|
3286
|
-
}
|
|
3287
|
-
};
|
|
3288
|
-
};
|
|
3289
|
-
var createInvokeCallback = (telemetry2) => {
|
|
3290
|
-
const invokeCallback = async (settings, invokeStep, context) => {
|
|
3291
|
-
const { body, workflow, headers = {}, workflowRunId = getWorkflowRunId(), retries } = settings;
|
|
3292
|
-
const { workflowId } = workflow;
|
|
3293
|
-
if (!workflowId) {
|
|
3294
|
-
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
3295
|
-
}
|
|
3296
|
-
const { headers: invokerHeaders } = getHeaders({
|
|
3297
|
-
initHeaderValue: "false",
|
|
3298
|
-
workflowRunId: context.workflowRunId,
|
|
3299
|
-
workflowUrl: context.url,
|
|
3300
|
-
userHeaders: context.headers,
|
|
3301
|
-
failureUrl: context.failureUrl,
|
|
3302
|
-
retries: context.retries,
|
|
3303
|
-
telemetry: telemetry2
|
|
3304
|
-
});
|
|
3305
|
-
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
3306
|
-
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
3307
|
-
const { headers: triggerHeaders } = getHeaders({
|
|
3308
|
-
initHeaderValue: "true",
|
|
3309
|
-
workflowRunId,
|
|
3310
|
-
workflowUrl: newUrl,
|
|
3311
|
-
userHeaders: new Headers(headers),
|
|
3312
|
-
retries,
|
|
3313
|
-
telemetry: telemetry2
|
|
3314
|
-
});
|
|
3315
|
-
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
3316
|
-
const request = {
|
|
3317
|
-
body: JSON.stringify(body),
|
|
3318
|
-
headers: Object.fromEntries(
|
|
3319
|
-
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
3320
|
-
),
|
|
3321
|
-
workflowRunId,
|
|
3322
|
-
workflowUrl: context.url,
|
|
3323
|
-
step: invokeStep
|
|
3324
|
-
};
|
|
3325
|
-
await context.qstashClient.publish({
|
|
3326
|
-
headers: triggerHeaders,
|
|
3327
|
-
method: "POST",
|
|
3328
|
-
body: JSON.stringify(request),
|
|
3329
|
-
url: newUrl
|
|
3330
|
-
});
|
|
3331
|
-
return void 0;
|
|
3332
|
-
};
|
|
3333
|
-
return invokeCallback;
|
|
3334
|
-
};
|
|
3335
|
-
|
|
3336
3478
|
// platforms/h3.ts
|
|
3337
3479
|
function transformHeaders(headers) {
|
|
3338
3480
|
const formattedHeaders = Object.entries(headers).map(([key, value]) => [
|
|
@@ -3374,21 +3516,19 @@ var serve = (routeFunction, options) => {
|
|
|
3374
3516
|
return { handler };
|
|
3375
3517
|
};
|
|
3376
3518
|
var createWorkflow = (...params) => {
|
|
3377
|
-
const
|
|
3519
|
+
const [routeFunction, options = {}] = params;
|
|
3378
3520
|
return {
|
|
3379
|
-
|
|
3380
|
-
|
|
3521
|
+
routeFunction,
|
|
3522
|
+
options,
|
|
3381
3523
|
workflowId: void 0
|
|
3382
3524
|
};
|
|
3383
3525
|
};
|
|
3384
|
-
var serveMany = (workflows) => {
|
|
3526
|
+
var serveMany = (workflows, options) => {
|
|
3385
3527
|
return serveManyBase({
|
|
3386
3528
|
workflows,
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
return components[components.length - 1];
|
|
3391
|
-
}
|
|
3529
|
+
getUrl,
|
|
3530
|
+
serveMethod: (...params) => serve(...params).handler,
|
|
3531
|
+
options
|
|
3392
3532
|
});
|
|
3393
3533
|
};
|
|
3394
3534
|
// Annotate the CommonJS export names for ESM import in node:
|