@rivetkit/workflow-engine 2.1.11-rc.1 → 2.2.1-pr.4600.b74ff3b
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/dist/tsup/{chunk-OYYWSC77.cjs → chunk-4SWXLWKL.cjs} +426 -54
- package/dist/tsup/chunk-4SWXLWKL.cjs.map +1 -0
- package/dist/tsup/{chunk-4ME2JBMC.js → chunk-UMFB2AR3.js} +426 -54
- package/dist/tsup/chunk-UMFB2AR3.js.map +1 -0
- package/dist/tsup/index.cjs +2 -2
- package/dist/tsup/index.d.cts +44 -1
- package/dist/tsup/index.d.ts +44 -1
- package/dist/tsup/index.js +1 -1
- package/dist/tsup/testing.cjs +23 -23
- package/dist/tsup/testing.d.cts +1 -1
- package/dist/tsup/testing.d.ts +1 -1
- package/dist/tsup/testing.js +1 -1
- package/package.json +1 -1
- package/src/context.ts +592 -75
- package/src/index.ts +8 -0
- package/src/types.ts +53 -0
- package/dist/tsup/chunk-4ME2JBMC.js.map +0 -1
- package/dist/tsup/chunk-OYYWSC77.cjs.map +0 -1
|
@@ -1658,7 +1658,19 @@ var DEFAULT_RETRY_BACKOFF_BASE = 100;
|
|
|
1658
1658
|
var DEFAULT_RETRY_BACKOFF_MAX = 3e4;
|
|
1659
1659
|
var DEFAULT_LOOP_HISTORY_PRUNE_INTERVAL = 20;
|
|
1660
1660
|
var DEFAULT_STEP_TIMEOUT = 3e4;
|
|
1661
|
+
var DEFAULT_TRY_STEP_CATCH = [
|
|
1662
|
+
"critical",
|
|
1663
|
+
"timeout",
|
|
1664
|
+
"exhausted"
|
|
1665
|
+
];
|
|
1666
|
+
var DEFAULT_TRY_BLOCK_CATCH = [
|
|
1667
|
+
"step",
|
|
1668
|
+
"join",
|
|
1669
|
+
"race"
|
|
1670
|
+
];
|
|
1661
1671
|
var QUEUE_HISTORY_MESSAGE_MARKER = "__rivetWorkflowQueueMessage";
|
|
1672
|
+
var TRY_STEP_FAILURE_SYMBOL = /* @__PURE__ */ Symbol("workflow.try-step.failure");
|
|
1673
|
+
var TRY_BLOCK_FAILURE_SYMBOL = /* @__PURE__ */ Symbol("workflow.try-block.failure");
|
|
1662
1674
|
function calculateBackoff(attempts, base, max) {
|
|
1663
1675
|
return Math.min(max, base * 2 ** attempts);
|
|
1664
1676
|
}
|
|
@@ -1670,6 +1682,128 @@ var StepTimeoutError = class extends Error {
|
|
|
1670
1682
|
this.name = "StepTimeoutError";
|
|
1671
1683
|
}
|
|
1672
1684
|
};
|
|
1685
|
+
function attachTryStepFailure(error, failure) {
|
|
1686
|
+
error[TRY_STEP_FAILURE_SYMBOL] = failure;
|
|
1687
|
+
return error;
|
|
1688
|
+
}
|
|
1689
|
+
function readTryStepFailure(error) {
|
|
1690
|
+
if (!(error instanceof Error)) {
|
|
1691
|
+
return void 0;
|
|
1692
|
+
}
|
|
1693
|
+
return error[TRY_STEP_FAILURE_SYMBOL];
|
|
1694
|
+
}
|
|
1695
|
+
function attachTryBlockFailure(error, failure) {
|
|
1696
|
+
error[TRY_BLOCK_FAILURE_SYMBOL] = failure;
|
|
1697
|
+
return error;
|
|
1698
|
+
}
|
|
1699
|
+
function readTryBlockFailure(error) {
|
|
1700
|
+
if (!(error instanceof Error)) {
|
|
1701
|
+
return void 0;
|
|
1702
|
+
}
|
|
1703
|
+
return error[TRY_BLOCK_FAILURE_SYMBOL];
|
|
1704
|
+
}
|
|
1705
|
+
function shouldRethrowTryError(error) {
|
|
1706
|
+
return error instanceof StepFailedError || error instanceof SleepError || error instanceof MessageWaitError || error instanceof EvictedError || error instanceof HistoryDivergedError || error instanceof EntryInProgressError || error instanceof RollbackCheckpointError || error instanceof RollbackStopError;
|
|
1707
|
+
}
|
|
1708
|
+
function shouldCatchTryStepFailure(failure, catchKinds) {
|
|
1709
|
+
const effectiveCatch = catchKinds ?? DEFAULT_TRY_STEP_CATCH;
|
|
1710
|
+
return effectiveCatch.includes(failure.kind);
|
|
1711
|
+
}
|
|
1712
|
+
function shouldCatchTryBlockFailure(failure, catchKinds) {
|
|
1713
|
+
var _a;
|
|
1714
|
+
const effectiveCatch = catchKinds ?? DEFAULT_TRY_BLOCK_CATCH;
|
|
1715
|
+
if (failure.source === "step") {
|
|
1716
|
+
return ((_a = failure.step) == null ? void 0 : _a.kind) === "rollback" ? effectiveCatch.includes("rollback") : effectiveCatch.includes("step");
|
|
1717
|
+
}
|
|
1718
|
+
if (failure.source === "join") {
|
|
1719
|
+
return effectiveCatch.includes("join");
|
|
1720
|
+
}
|
|
1721
|
+
if (failure.source === "race") {
|
|
1722
|
+
return effectiveCatch.includes("race");
|
|
1723
|
+
}
|
|
1724
|
+
return effectiveCatch.includes("rollback");
|
|
1725
|
+
}
|
|
1726
|
+
function parseStoredWorkflowError(message) {
|
|
1727
|
+
if (!message) {
|
|
1728
|
+
return {
|
|
1729
|
+
name: "Error",
|
|
1730
|
+
message: "unknown error"
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
const match = /^([^:]+):\s*(.*)$/s.exec(message);
|
|
1734
|
+
if (!match) {
|
|
1735
|
+
return {
|
|
1736
|
+
name: "Error",
|
|
1737
|
+
message
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
return {
|
|
1741
|
+
name: match[1],
|
|
1742
|
+
message: match[2]
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
function getTryStepFailureFromExhaustedError(stepName, attempts, error) {
|
|
1746
|
+
return {
|
|
1747
|
+
kind: "exhausted",
|
|
1748
|
+
stepName,
|
|
1749
|
+
attempts,
|
|
1750
|
+
error: parseStoredWorkflowError(error.lastError)
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
function mergeSchedulerYield(state, error) {
|
|
1754
|
+
const nextState = state ?? {
|
|
1755
|
+
messageNames: /* @__PURE__ */ new Set()
|
|
1756
|
+
};
|
|
1757
|
+
if (error instanceof SleepError) {
|
|
1758
|
+
nextState.deadline = nextState.deadline === void 0 ? error.deadline : Math.min(nextState.deadline, error.deadline);
|
|
1759
|
+
for (const messageName of error.messageNames ?? []) {
|
|
1760
|
+
nextState.messageNames.add(messageName);
|
|
1761
|
+
}
|
|
1762
|
+
return nextState;
|
|
1763
|
+
}
|
|
1764
|
+
if (error instanceof MessageWaitError) {
|
|
1765
|
+
for (const messageName of error.messageNames) {
|
|
1766
|
+
nextState.messageNames.add(messageName);
|
|
1767
|
+
}
|
|
1768
|
+
return nextState;
|
|
1769
|
+
}
|
|
1770
|
+
nextState.deadline = nextState.deadline === void 0 ? error.retryAt : Math.min(nextState.deadline, error.retryAt);
|
|
1771
|
+
return nextState;
|
|
1772
|
+
}
|
|
1773
|
+
function buildSchedulerYieldError(state) {
|
|
1774
|
+
const messageNames = [...state.messageNames];
|
|
1775
|
+
if (state.deadline !== void 0) {
|
|
1776
|
+
return new SleepError(
|
|
1777
|
+
state.deadline,
|
|
1778
|
+
messageNames.length > 0 ? messageNames : void 0
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1781
|
+
return new MessageWaitError(messageNames);
|
|
1782
|
+
}
|
|
1783
|
+
function controlFlowErrorPriority(error) {
|
|
1784
|
+
if (error instanceof EvictedError) {
|
|
1785
|
+
return 0;
|
|
1786
|
+
}
|
|
1787
|
+
if (error instanceof HistoryDivergedError) {
|
|
1788
|
+
return 1;
|
|
1789
|
+
}
|
|
1790
|
+
if (error instanceof EntryInProgressError) {
|
|
1791
|
+
return 2;
|
|
1792
|
+
}
|
|
1793
|
+
if (error instanceof RollbackCheckpointError) {
|
|
1794
|
+
return 3;
|
|
1795
|
+
}
|
|
1796
|
+
if (error instanceof RollbackStopError) {
|
|
1797
|
+
return 4;
|
|
1798
|
+
}
|
|
1799
|
+
return 5;
|
|
1800
|
+
}
|
|
1801
|
+
function selectControlFlowError(current, candidate) {
|
|
1802
|
+
if (!current) {
|
|
1803
|
+
return candidate;
|
|
1804
|
+
}
|
|
1805
|
+
return controlFlowErrorPriority(candidate) < controlFlowErrorPriority(current) ? candidate : current;
|
|
1806
|
+
}
|
|
1673
1807
|
var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
1674
1808
|
constructor(workflowId, storage, driver, messageDriver, location = emptyLocation(), abortController, mode = "forward", rollbackActions, rollbackCheckpointSet = false, historyNotifier, onError, logger, visitedKeys) {
|
|
1675
1809
|
this.workflowId = workflowId;
|
|
@@ -1896,6 +2030,110 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
1896
2030
|
this.entryInProgress = false;
|
|
1897
2031
|
}
|
|
1898
2032
|
}
|
|
2033
|
+
async tryStep(nameOrConfig, run) {
|
|
2034
|
+
const config2 = typeof nameOrConfig === "string" ? {
|
|
2035
|
+
name: nameOrConfig,
|
|
2036
|
+
run
|
|
2037
|
+
} : nameOrConfig;
|
|
2038
|
+
try {
|
|
2039
|
+
return {
|
|
2040
|
+
ok: true,
|
|
2041
|
+
value: await this.step(config2)
|
|
2042
|
+
};
|
|
2043
|
+
} catch (error) {
|
|
2044
|
+
if (shouldRethrowTryError(error)) {
|
|
2045
|
+
throw error;
|
|
2046
|
+
}
|
|
2047
|
+
const failure = readTryStepFailure(error);
|
|
2048
|
+
if (!failure || !shouldCatchTryStepFailure(failure, config2.catch)) {
|
|
2049
|
+
throw error;
|
|
2050
|
+
}
|
|
2051
|
+
return {
|
|
2052
|
+
ok: false,
|
|
2053
|
+
failure
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
async try(nameOrConfig, run) {
|
|
2058
|
+
this.assertNotInProgress();
|
|
2059
|
+
this.checkEvicted();
|
|
2060
|
+
const config2 = typeof nameOrConfig === "string" ? {
|
|
2061
|
+
name: nameOrConfig,
|
|
2062
|
+
run
|
|
2063
|
+
} : nameOrConfig;
|
|
2064
|
+
this.entryInProgress = true;
|
|
2065
|
+
try {
|
|
2066
|
+
return await this.executeTry(config2);
|
|
2067
|
+
} finally {
|
|
2068
|
+
this.entryInProgress = false;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
async executeTry(config2) {
|
|
2072
|
+
this.checkDuplicateName(config2.name);
|
|
2073
|
+
const location = appendName(
|
|
2074
|
+
this.storage,
|
|
2075
|
+
this.currentLocation,
|
|
2076
|
+
config2.name
|
|
2077
|
+
);
|
|
2078
|
+
const blockCtx = this.createBranch(location);
|
|
2079
|
+
try {
|
|
2080
|
+
const value = await config2.run(blockCtx);
|
|
2081
|
+
blockCtx.validateComplete();
|
|
2082
|
+
return {
|
|
2083
|
+
ok: true,
|
|
2084
|
+
value
|
|
2085
|
+
};
|
|
2086
|
+
} catch (error) {
|
|
2087
|
+
if (shouldRethrowTryError(error)) {
|
|
2088
|
+
throw error;
|
|
2089
|
+
}
|
|
2090
|
+
const stepFailure = readTryStepFailure(error);
|
|
2091
|
+
if (stepFailure) {
|
|
2092
|
+
const failure = {
|
|
2093
|
+
source: "step",
|
|
2094
|
+
name: stepFailure.stepName,
|
|
2095
|
+
error: stepFailure.error,
|
|
2096
|
+
step: stepFailure
|
|
2097
|
+
};
|
|
2098
|
+
if (!shouldCatchTryBlockFailure(failure, config2.catch)) {
|
|
2099
|
+
throw error;
|
|
2100
|
+
}
|
|
2101
|
+
return {
|
|
2102
|
+
ok: false,
|
|
2103
|
+
failure
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2106
|
+
const operationFailure = readTryBlockFailure(error);
|
|
2107
|
+
if (operationFailure) {
|
|
2108
|
+
const failure = {
|
|
2109
|
+
...operationFailure,
|
|
2110
|
+
error: extractErrorInfo(error)
|
|
2111
|
+
};
|
|
2112
|
+
if (!shouldCatchTryBlockFailure(failure, config2.catch)) {
|
|
2113
|
+
throw error;
|
|
2114
|
+
}
|
|
2115
|
+
return {
|
|
2116
|
+
ok: false,
|
|
2117
|
+
failure
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2120
|
+
if (error instanceof RollbackError) {
|
|
2121
|
+
const failure = {
|
|
2122
|
+
source: "block",
|
|
2123
|
+
name: config2.name,
|
|
2124
|
+
error: extractErrorInfo(error)
|
|
2125
|
+
};
|
|
2126
|
+
if (!shouldCatchTryBlockFailure(failure, config2.catch)) {
|
|
2127
|
+
throw error;
|
|
2128
|
+
}
|
|
2129
|
+
return {
|
|
2130
|
+
ok: false,
|
|
2131
|
+
failure
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
throw error;
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
1899
2137
|
async executeStep(config2) {
|
|
1900
2138
|
this.ensureRollbackCheckpoint(config2);
|
|
1901
2139
|
if (this.mode === "rollback") {
|
|
@@ -1928,9 +2166,19 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
1928
2166
|
const maxRetries2 = config2.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
1929
2167
|
if (metadata2.attempts > maxRetries2) {
|
|
1930
2168
|
const lastError = stepData.error ?? metadata2.error;
|
|
1931
|
-
const exhaustedError =
|
|
1932
|
-
|
|
2169
|
+
const exhaustedError = new StepExhaustedError(
|
|
2170
|
+
config2.name,
|
|
2171
|
+
lastError
|
|
1933
2172
|
);
|
|
2173
|
+
attachTryStepFailure(
|
|
2174
|
+
exhaustedError,
|
|
2175
|
+
getTryStepFailureFromExhaustedError(
|
|
2176
|
+
config2.name,
|
|
2177
|
+
metadata2.attempts,
|
|
2178
|
+
exhaustedError
|
|
2179
|
+
)
|
|
2180
|
+
);
|
|
2181
|
+
markErrorReported(exhaustedError);
|
|
1934
2182
|
if (metadata2.status !== "exhausted") {
|
|
1935
2183
|
metadata2.status = "exhausted";
|
|
1936
2184
|
metadata2.dirty = true;
|
|
@@ -2017,7 +2265,17 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2017
2265
|
await this.notifyStepError(config2, metadata.attempts, error, {
|
|
2018
2266
|
willRetry: false
|
|
2019
2267
|
});
|
|
2020
|
-
throw markErrorReported(
|
|
2268
|
+
throw markErrorReported(
|
|
2269
|
+
attachTryStepFailure(
|
|
2270
|
+
new CriticalError(error.message),
|
|
2271
|
+
{
|
|
2272
|
+
kind: "timeout",
|
|
2273
|
+
stepName: config2.name,
|
|
2274
|
+
attempts: metadata.attempts,
|
|
2275
|
+
error: extractErrorInfo(error)
|
|
2276
|
+
}
|
|
2277
|
+
)
|
|
2278
|
+
);
|
|
2021
2279
|
}
|
|
2022
2280
|
if (error instanceof CriticalError || error instanceof RollbackError) {
|
|
2023
2281
|
if (entry.kind.type === "step") {
|
|
@@ -2030,7 +2288,14 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2030
2288
|
await this.notifyStepError(config2, metadata.attempts, error, {
|
|
2031
2289
|
willRetry: false
|
|
2032
2290
|
});
|
|
2033
|
-
throw markErrorReported(
|
|
2291
|
+
throw markErrorReported(
|
|
2292
|
+
attachTryStepFailure(error, {
|
|
2293
|
+
kind: error instanceof RollbackError ? "rollback" : "critical",
|
|
2294
|
+
stepName: config2.name,
|
|
2295
|
+
attempts: metadata.attempts,
|
|
2296
|
+
error: extractErrorInfo(error)
|
|
2297
|
+
})
|
|
2298
|
+
);
|
|
2034
2299
|
}
|
|
2035
2300
|
if (entry.kind.type === "step") {
|
|
2036
2301
|
entry.kind.data.error = String(error);
|
|
@@ -2060,7 +2325,15 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2060
2325
|
);
|
|
2061
2326
|
}
|
|
2062
2327
|
const exhaustedError = markErrorReported(
|
|
2063
|
-
|
|
2328
|
+
attachTryStepFailure(
|
|
2329
|
+
new StepExhaustedError(config2.name, String(error)),
|
|
2330
|
+
{
|
|
2331
|
+
kind: "exhausted",
|
|
2332
|
+
stepName: config2.name,
|
|
2333
|
+
attempts: metadata.attempts,
|
|
2334
|
+
error: extractErrorInfo(error)
|
|
2335
|
+
}
|
|
2336
|
+
)
|
|
2064
2337
|
);
|
|
2065
2338
|
await this.notifyStepError(config2, metadata.attempts, error, {
|
|
2066
2339
|
willRetry: false
|
|
@@ -2835,9 +3108,29 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2835
3108
|
const joinData = entry.kind.data;
|
|
2836
3109
|
const results = {};
|
|
2837
3110
|
const errors = {};
|
|
3111
|
+
let schedulerYieldState;
|
|
3112
|
+
let propagatedError;
|
|
3113
|
+
for (const [branchName, branchStatus] of Object.entries(
|
|
3114
|
+
joinData.branches
|
|
3115
|
+
)) {
|
|
3116
|
+
if (branchStatus.status === "completed") {
|
|
3117
|
+
results[branchName] = branchStatus.output;
|
|
3118
|
+
continue;
|
|
3119
|
+
}
|
|
3120
|
+
if (branchStatus.status === "failed") {
|
|
3121
|
+
errors[branchName] = new Error(
|
|
3122
|
+
branchStatus.error ?? "branch failed"
|
|
3123
|
+
);
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
2838
3126
|
const branchPromises = Object.entries(branches).map(
|
|
2839
3127
|
async ([branchName, config2]) => {
|
|
2840
3128
|
const branchStatus = joinData.branches[branchName];
|
|
3129
|
+
if (!branchStatus) {
|
|
3130
|
+
throw new HistoryDivergedError(
|
|
3131
|
+
`Expected join branch "${branchName}" in "${name}"`
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
2841
3134
|
if (branchStatus.status === "completed") {
|
|
2842
3135
|
results[branchName] = branchStatus.output;
|
|
2843
3136
|
return;
|
|
@@ -2853,15 +3146,38 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2853
3146
|
);
|
|
2854
3147
|
const branchCtx = this.createBranch(branchLocation);
|
|
2855
3148
|
branchStatus.status = "running";
|
|
3149
|
+
branchStatus.error = void 0;
|
|
2856
3150
|
entry.dirty = true;
|
|
2857
3151
|
try {
|
|
2858
3152
|
const output = await config2.run(branchCtx);
|
|
2859
3153
|
branchCtx.validateComplete();
|
|
2860
3154
|
branchStatus.status = "completed";
|
|
2861
3155
|
branchStatus.output = output;
|
|
3156
|
+
branchStatus.error = void 0;
|
|
2862
3157
|
results[branchName] = output;
|
|
2863
3158
|
} catch (error) {
|
|
3159
|
+
if (error instanceof SleepError || error instanceof MessageWaitError || error instanceof StepFailedError) {
|
|
3160
|
+
schedulerYieldState = mergeSchedulerYield(
|
|
3161
|
+
schedulerYieldState,
|
|
3162
|
+
error
|
|
3163
|
+
);
|
|
3164
|
+
branchStatus.status = "running";
|
|
3165
|
+
branchStatus.error = void 0;
|
|
3166
|
+
entry.dirty = true;
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3169
|
+
if (error instanceof EvictedError || error instanceof HistoryDivergedError || error instanceof EntryInProgressError || error instanceof RollbackCheckpointError || error instanceof RollbackStopError) {
|
|
3170
|
+
propagatedError = selectControlFlowError(
|
|
3171
|
+
propagatedError,
|
|
3172
|
+
error
|
|
3173
|
+
);
|
|
3174
|
+
branchStatus.status = "running";
|
|
3175
|
+
branchStatus.error = void 0;
|
|
3176
|
+
entry.dirty = true;
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
2864
3179
|
branchStatus.status = "failed";
|
|
3180
|
+
branchStatus.output = void 0;
|
|
2865
3181
|
branchStatus.error = String(error);
|
|
2866
3182
|
errors[branchName] = error;
|
|
2867
3183
|
}
|
|
@@ -2870,8 +3186,24 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2870
3186
|
);
|
|
2871
3187
|
await Promise.allSettled(branchPromises);
|
|
2872
3188
|
await this.flushStorage();
|
|
3189
|
+
if (propagatedError) {
|
|
3190
|
+
throw propagatedError;
|
|
3191
|
+
}
|
|
3192
|
+
if (Object.values(joinData.branches).some(
|
|
3193
|
+
(branch) => branch.status === "pending" || branch.status === "running"
|
|
3194
|
+
)) {
|
|
3195
|
+
if (!schedulerYieldState) {
|
|
3196
|
+
throw new Error(
|
|
3197
|
+
`Join "${name}" has pending branches without a scheduler yield`
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
throw buildSchedulerYieldError(schedulerYieldState);
|
|
3201
|
+
}
|
|
2873
3202
|
if (Object.keys(errors).length > 0) {
|
|
2874
|
-
throw new JoinError(errors)
|
|
3203
|
+
throw attachTryBlockFailure(new JoinError(errors), {
|
|
3204
|
+
source: "join",
|
|
3205
|
+
name
|
|
3206
|
+
});
|
|
2875
3207
|
}
|
|
2876
3208
|
return results;
|
|
2877
3209
|
}
|
|
@@ -2934,28 +3266,42 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2934
3266
|
const raceAbortController = new AbortController();
|
|
2935
3267
|
const branchPromises = [];
|
|
2936
3268
|
let winnerName = null;
|
|
2937
|
-
let winnerValue
|
|
2938
|
-
let
|
|
2939
|
-
let pendingCount = branches.length;
|
|
3269
|
+
let winnerValue;
|
|
3270
|
+
let hasWinner = false;
|
|
2940
3271
|
const errors = {};
|
|
2941
3272
|
const lateErrors = [];
|
|
2942
|
-
let
|
|
3273
|
+
let schedulerYieldState;
|
|
3274
|
+
let propagatedError;
|
|
2943
3275
|
for (const branch of branches) {
|
|
2944
3276
|
const branchStatus = raceData.branches[branch.name];
|
|
3277
|
+
if (!branchStatus) {
|
|
3278
|
+
throw new HistoryDivergedError(
|
|
3279
|
+
`Expected race branch "${branch.name}" in "${name}"`
|
|
3280
|
+
);
|
|
3281
|
+
}
|
|
2945
3282
|
if (branchStatus.status !== "pending" && branchStatus.status !== "running") {
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
3283
|
+
if (branchStatus.status === "failed") {
|
|
3284
|
+
errors[branch.name] = new Error(
|
|
3285
|
+
branchStatus.error ?? "branch failed"
|
|
3286
|
+
);
|
|
3287
|
+
}
|
|
3288
|
+
if (branchStatus.status === "completed" && !hasWinner) {
|
|
3289
|
+
hasWinner = true;
|
|
2949
3290
|
winnerName = branch.name;
|
|
2950
3291
|
winnerValue = branchStatus.output;
|
|
2951
3292
|
}
|
|
2952
3293
|
}
|
|
2953
3294
|
}
|
|
2954
|
-
if (
|
|
3295
|
+
if (hasWinner && winnerName !== null) {
|
|
2955
3296
|
return { winner: winnerName, value: winnerValue };
|
|
2956
3297
|
}
|
|
2957
3298
|
for (const branch of branches) {
|
|
2958
3299
|
const branchStatus = raceData.branches[branch.name];
|
|
3300
|
+
if (!branchStatus) {
|
|
3301
|
+
throw new HistoryDivergedError(
|
|
3302
|
+
`Expected race branch "${branch.name}" in "${name}"`
|
|
3303
|
+
);
|
|
3304
|
+
}
|
|
2959
3305
|
if (branchStatus.status !== "pending" && branchStatus.status !== "running") {
|
|
2960
3306
|
continue;
|
|
2961
3307
|
}
|
|
@@ -2969,78 +3315,98 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
2969
3315
|
raceAbortController
|
|
2970
3316
|
);
|
|
2971
3317
|
branchStatus.status = "running";
|
|
3318
|
+
branchStatus.error = void 0;
|
|
2972
3319
|
entry.dirty = true;
|
|
2973
3320
|
const branchPromise = branch.run(branchCtx).then(
|
|
2974
3321
|
async (output) => {
|
|
2975
|
-
if (
|
|
3322
|
+
if (hasWinner) {
|
|
3323
|
+
branchStatus.status = "completed";
|
|
3324
|
+
branchStatus.output = output;
|
|
3325
|
+
branchStatus.error = void 0;
|
|
3326
|
+
entry.dirty = true;
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
if (propagatedError) {
|
|
2976
3330
|
branchStatus.status = "completed";
|
|
2977
3331
|
branchStatus.output = output;
|
|
3332
|
+
branchStatus.error = void 0;
|
|
2978
3333
|
entry.dirty = true;
|
|
2979
3334
|
return;
|
|
2980
3335
|
}
|
|
2981
|
-
|
|
3336
|
+
hasWinner = true;
|
|
2982
3337
|
winnerName = branch.name;
|
|
2983
3338
|
winnerValue = output;
|
|
2984
3339
|
branchCtx.validateComplete();
|
|
2985
3340
|
branchStatus.status = "completed";
|
|
2986
3341
|
branchStatus.output = output;
|
|
3342
|
+
branchStatus.error = void 0;
|
|
2987
3343
|
raceData.winner = branch.name;
|
|
2988
3344
|
entry.dirty = true;
|
|
2989
3345
|
raceAbortController.abort();
|
|
2990
3346
|
},
|
|
2991
3347
|
(error) => {
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
3348
|
+
if (hasWinner) {
|
|
3349
|
+
if (error instanceof CancelledError || error instanceof EvictedError) {
|
|
3350
|
+
branchStatus.status = "cancelled";
|
|
3351
|
+
} else {
|
|
3352
|
+
lateErrors.push({
|
|
3353
|
+
name: branch.name,
|
|
3354
|
+
error: String(error)
|
|
3355
|
+
});
|
|
2996
3356
|
}
|
|
3357
|
+
entry.dirty = true;
|
|
3358
|
+
return;
|
|
3359
|
+
}
|
|
3360
|
+
if (error instanceof SleepError || error instanceof MessageWaitError || error instanceof StepFailedError) {
|
|
3361
|
+
schedulerYieldState = mergeSchedulerYield(
|
|
3362
|
+
schedulerYieldState,
|
|
3363
|
+
error
|
|
3364
|
+
);
|
|
2997
3365
|
branchStatus.status = "running";
|
|
3366
|
+
branchStatus.error = void 0;
|
|
2998
3367
|
entry.dirty = true;
|
|
2999
3368
|
return;
|
|
3000
3369
|
}
|
|
3001
|
-
if (error instanceof
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
yieldError = new MessageWaitError([
|
|
3007
|
-
...yieldError.messageNames,
|
|
3008
|
-
...error.messageNames
|
|
3009
|
-
]);
|
|
3010
|
-
}
|
|
3011
|
-
}
|
|
3370
|
+
if (error instanceof EvictedError || error instanceof HistoryDivergedError || error instanceof EntryInProgressError || error instanceof RollbackCheckpointError || error instanceof RollbackStopError) {
|
|
3371
|
+
propagatedError = selectControlFlowError(
|
|
3372
|
+
propagatedError,
|
|
3373
|
+
error
|
|
3374
|
+
);
|
|
3012
3375
|
branchStatus.status = "running";
|
|
3376
|
+
branchStatus.error = void 0;
|
|
3013
3377
|
entry.dirty = true;
|
|
3014
3378
|
return;
|
|
3015
3379
|
}
|
|
3016
|
-
if (error instanceof CancelledError
|
|
3380
|
+
if (error instanceof CancelledError) {
|
|
3017
3381
|
branchStatus.status = "cancelled";
|
|
3018
3382
|
} else {
|
|
3019
3383
|
branchStatus.status = "failed";
|
|
3384
|
+
branchStatus.output = void 0;
|
|
3020
3385
|
branchStatus.error = String(error);
|
|
3021
|
-
|
|
3022
|
-
lateErrors.push({
|
|
3023
|
-
name: branch.name,
|
|
3024
|
-
error: String(error)
|
|
3025
|
-
});
|
|
3026
|
-
} else {
|
|
3027
|
-
errors[branch.name] = error;
|
|
3028
|
-
}
|
|
3386
|
+
errors[branch.name] = error;
|
|
3029
3387
|
}
|
|
3030
3388
|
entry.dirty = true;
|
|
3031
|
-
if (pendingCount === 0 && !settled) {
|
|
3032
|
-
settled = true;
|
|
3033
|
-
}
|
|
3034
3389
|
}
|
|
3035
3390
|
);
|
|
3036
3391
|
branchPromises.push(branchPromise);
|
|
3037
3392
|
}
|
|
3038
3393
|
await Promise.allSettled(branchPromises);
|
|
3039
|
-
if (
|
|
3394
|
+
if (propagatedError) {
|
|
3395
|
+
await this.flushStorage();
|
|
3396
|
+
throw propagatedError;
|
|
3397
|
+
}
|
|
3398
|
+
if (!hasWinner && Object.values(raceData.branches).some(
|
|
3399
|
+
(branch) => branch.status === "pending" || branch.status === "running"
|
|
3400
|
+
)) {
|
|
3040
3401
|
await this.flushStorage();
|
|
3041
|
-
|
|
3402
|
+
if (!schedulerYieldState) {
|
|
3403
|
+
throw new Error(
|
|
3404
|
+
`Race "${name}" has pending branches without a scheduler yield`
|
|
3405
|
+
);
|
|
3406
|
+
}
|
|
3407
|
+
throw buildSchedulerYieldError(schedulerYieldState);
|
|
3042
3408
|
}
|
|
3043
|
-
if (winnerName !== null) {
|
|
3409
|
+
if (hasWinner && winnerName !== null) {
|
|
3044
3410
|
for (const branch of branches) {
|
|
3045
3411
|
if (branch.name !== winnerName) {
|
|
3046
3412
|
const branchLocation = appendName(
|
|
@@ -3064,15 +3430,21 @@ var WorkflowContextImpl = class _WorkflowContextImpl {
|
|
|
3064
3430
|
lateErrors
|
|
3065
3431
|
);
|
|
3066
3432
|
}
|
|
3067
|
-
if (
|
|
3433
|
+
if (hasWinner && winnerName !== null) {
|
|
3068
3434
|
return { winner: winnerName, value: winnerValue };
|
|
3069
3435
|
}
|
|
3070
|
-
throw
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3436
|
+
throw attachTryBlockFailure(
|
|
3437
|
+
new RaceError(
|
|
3438
|
+
"All branches failed",
|
|
3439
|
+
Object.entries(errors).map(([branchName, error]) => ({
|
|
3440
|
+
name: branchName,
|
|
3441
|
+
error: String(error)
|
|
3442
|
+
}))
|
|
3443
|
+
),
|
|
3444
|
+
{
|
|
3445
|
+
source: "race",
|
|
3446
|
+
name
|
|
3447
|
+
}
|
|
3076
3448
|
);
|
|
3077
3449
|
}
|
|
3078
3450
|
// === Removed ===
|
|
@@ -3805,4 +4177,4 @@ export {
|
|
|
3805
4177
|
runWorkflow,
|
|
3806
4178
|
replayWorkflowFromStep
|
|
3807
4179
|
};
|
|
3808
|
-
//# sourceMappingURL=chunk-
|
|
4180
|
+
//# sourceMappingURL=chunk-UMFB2AR3.js.map
|