@ferricstore/ferricstore 0.12.2 → 0.13.1
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/README.md +45 -3
- package/dist/index.cjs +804 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -9
- package/dist/index.d.ts +87 -9
- package/dist/index.js +798 -194
- package/dist/index.js.map +1 -1
- package/dist/langgraph.cjs.map +1 -1
- package/dist/langgraph.d.cts +1 -1
- package/dist/langgraph.d.ts +1 -1
- package/dist/langgraph.js.map +1 -1
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.js.map +1 -1
- package/dist/{outcomes-DmBwnq0Y.d.cts → outcomes-CcX956h4.d.cts} +20 -1
- package/dist/{outcomes-BbFDp3AH.d.ts → outcomes-DLJYTrX8.d.ts} +20 -1
- package/docs/api/assets/hierarchy.js +1 -1
- package/docs/api/assets/highlight.css +9 -2
- package/docs/api/assets/navigation.js +1 -1
- package/docs/api/assets/search.js +1 -1
- package/docs/api/classes/ConnectionClosedError.html +5 -5
- package/docs/api/classes/FerricStoreClient.html +68 -23
- package/docs/api/classes/FerricStoreError.html +2 -1
- package/docs/api/classes/FlowAlreadyExistsError.html +3 -3
- package/docs/api/classes/FlowBatchError.html +1 -1
- package/docs/api/classes/FlowNotFoundError.html +3 -3
- package/docs/api/classes/FlowQueryError.html +1 -1
- package/docs/api/classes/FlowWrongStateError.html +3 -3
- package/docs/api/classes/HTTPTransportError.html +14 -8
- package/docs/api/classes/InvalidCommandError.html +3 -3
- package/docs/api/classes/LeaseRenewalError.html +3 -3
- package/docs/api/classes/LockHeldError.html +3 -3
- package/docs/api/classes/LockNotOwnedError.html +3 -3
- package/docs/api/classes/NativeAdapter.html +3 -3
- package/docs/api/classes/OverloadedError.html +5 -5
- package/docs/api/classes/QueueCompletionError.html +1 -1
- package/docs/api/classes/RequestNotSentError.html +225 -0
- package/docs/api/classes/RequestTimeoutError.html +6 -6
- package/docs/api/classes/RerouteError.html +3 -3
- package/docs/api/classes/StaleLeaseError.html +3 -3
- package/docs/api/classes/StalePolicyGenerationError.html +3 -3
- package/docs/api/classes/Workflow.html +19 -19
- package/docs/api/classes/WorkflowClient.html +4 -4
- package/docs/api/classes/WorkflowContext.html +73 -37
- package/docs/api/classes/WorkflowFlowCommands.html +26 -22
- package/docs/api/classes/WorkflowWorker.html +6 -6
- package/docs/api/functions/classifyServerError.html +1 -1
- package/docs/api/functions/complete.html +1 -1
- package/docs/api/functions/fail.html +1 -1
- package/docs/api/functions/isAlreadyAppliedOutcome.html +41 -0
- package/docs/api/functions/isOutcome.html +1 -1
- package/docs/api/functions/mapException.html +1 -1
- package/docs/api/functions/retry.html +1 -1
- package/docs/api/functions/transition.html +1 -1
- package/docs/api/hierarchy.html +56 -47
- package/docs/api/index.html +32 -4
- package/docs/api/interfaces/AdminListOptions.html +1 -1
- package/docs/api/interfaces/AdvanceOptions.html +145 -0
- package/docs/api/interfaces/AlreadyAppliedOutcome.html +69 -0
- package/docs/api/interfaces/AppliedStepOutcome.html +87 -0
- package/docs/api/interfaces/CancelOptions.html +13 -9
- package/docs/api/interfaces/CompleteOptions.html +13 -9
- package/docs/api/interfaces/CompleteOutcome.html +13 -13
- package/docs/api/interfaces/CreateManyOptions.html +1 -1
- package/docs/api/interfaces/EffectCompensateOptions.html +1 -1
- package/docs/api/interfaces/EffectConfirmOptions.html +1 -1
- package/docs/api/interfaces/EffectFailOptions.html +1 -1
- package/docs/api/interfaces/EffectStatusOptions.html +1 -1
- package/docs/api/interfaces/ExtendLeaseOptions.html +10 -8
- package/docs/api/interfaces/FailOptions.html +13 -9
- package/docs/api/interfaces/FailOutcome.html +13 -13
- package/docs/api/interfaces/FerricStoreClientFromUrlOptions.html +1 -1
- package/docs/api/interfaces/FerricStoreClientOptions.html +1 -1
- package/docs/api/interfaces/FlowQueryCountResult.html +1 -1
- package/docs/api/interfaces/FlowQueryIndexBuild.html +1 -1
- package/docs/api/interfaces/FlowQueryIndexProgress.html +1 -1
- package/docs/api/interfaces/FlowQueryIndexValidation.html +1 -1
- package/docs/api/interfaces/FlowQueryRecordsResult.html +1 -1
- package/docs/api/interfaces/HistoryOptions.html +16 -16
- package/docs/api/interfaces/InvocationCreateOptions.html +1 -1
- package/docs/api/interfaces/LeaseMutationOptions.html +11 -7
- package/docs/api/interfaces/LimitListOptions.html +1 -1
- package/docs/api/interfaces/MutateOptions.html +8 -4
- package/docs/api/interfaces/NamedValueMutation.html +9 -9
- package/docs/api/interfaces/ReadOptions.html +12 -12
- package/docs/api/interfaces/ReclaimOptions.html +1 -1
- package/docs/api/interfaces/ReplayedStepResult.html +73 -0
- package/docs/api/interfaces/RequestContextOptions.html +1 -1
- package/docs/api/interfaces/RetryOptions.html +13 -9
- package/docs/api/interfaces/RetryOutcome.html +13 -13
- package/docs/api/interfaces/RunStepsItem.html +3 -3
- package/docs/api/interfaces/RunStepsManyOptions.html +11 -11
- package/docs/api/interfaces/SearchOptions.html +13 -13
- package/docs/api/interfaces/StepContinueOptions.html +16 -12
- package/docs/api/interfaces/StepOptions.html +166 -0
- package/docs/api/interfaces/StepResult.html +67 -0
- package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
- package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
- package/docs/api/interfaces/TransitionOptions.html +15 -11
- package/docs/api/interfaces/TransitionOutcome.html +14 -14
- package/docs/api/media/design.md +12 -1
- package/docs/api/modules.html +8 -8
- package/docs/api/types/ConnectionRequestDisposition.html +1 -1
- package/docs/api/types/ManagementPairs.html +1 -1
- package/docs/api/types/Outcome.html +1 -1
- package/docs/api/types/RequestDisposition.html +1 -1
- package/docs/api/types/SearchStateMeta.html +1 -1
- package/docs/api/types/WorkflowStepResult.html +38 -0
- package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +1 -1
- package/docs/design.md +12 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,9 +30,16 @@ var FerricStoreError = class extends Error {
|
|
|
30
30
|
};
|
|
31
31
|
var HTTPTransportError = class extends FerricStoreError {
|
|
32
32
|
code = "http_transport";
|
|
33
|
+
requestDisposition;
|
|
33
34
|
statusCode;
|
|
34
35
|
constructor(message, options = {}) {
|
|
35
|
-
|
|
36
|
+
const disposition = options.requestDisposition;
|
|
37
|
+
super(message, {
|
|
38
|
+
...options,
|
|
39
|
+
retryable: options.retryable ?? (disposition === "unsent" ? false : void 0),
|
|
40
|
+
safeToRetry: options.safeToRetry ?? (disposition === "unsent" ? true : disposition === "possibly_sent" ? false : void 0)
|
|
41
|
+
});
|
|
42
|
+
this.requestDisposition = disposition;
|
|
36
43
|
this.statusCode = options.statusCode;
|
|
37
44
|
}
|
|
38
45
|
};
|
|
@@ -57,6 +64,20 @@ var RequestTimeoutError = class extends FerricStoreError {
|
|
|
57
64
|
this.timeoutMs = timeoutMs;
|
|
58
65
|
}
|
|
59
66
|
};
|
|
67
|
+
var RequestNotSentError = class extends FerricStoreError {
|
|
68
|
+
code = "request_not_sent";
|
|
69
|
+
requestDisposition = "unsent";
|
|
70
|
+
constructor(message, options = {}) {
|
|
71
|
+
super(message, { ...options, retryable: false, safeToRetry: true });
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
function requestNotSentError(error, message) {
|
|
75
|
+
if (error instanceof RequestNotSentError) return error;
|
|
76
|
+
return new RequestNotSentError(
|
|
77
|
+
message ?? (error instanceof Error ? error.message : String(error)),
|
|
78
|
+
{ cause: error, raw: error }
|
|
79
|
+
);
|
|
80
|
+
}
|
|
60
81
|
var FlowNotFoundError = class extends FerricStoreError {
|
|
61
82
|
code = "flow_not_found";
|
|
62
83
|
};
|
|
@@ -6315,7 +6336,10 @@ function decodeCompactPipeline(data, budget, claimModes) {
|
|
|
6315
6336
|
);
|
|
6316
6337
|
offset = read.offset;
|
|
6317
6338
|
} else {
|
|
6318
|
-
throw new FerricStoreError(
|
|
6339
|
+
throw new FerricStoreError(`unknown compact pipeline status ${status}`, {
|
|
6340
|
+
retryable: false,
|
|
6341
|
+
safeToRetry: false
|
|
6342
|
+
});
|
|
6319
6343
|
}
|
|
6320
6344
|
}
|
|
6321
6345
|
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact pipeline bytes");
|
|
@@ -6485,6 +6509,7 @@ var COUNTED_COMPACT_TAGS = /* @__PURE__ */ new Set([
|
|
|
6485
6509
|
]);
|
|
6486
6510
|
|
|
6487
6511
|
// src/protocol-response.ts
|
|
6512
|
+
var KNOWN_NATIVE_RESPONSE_STATUSES = /* @__PURE__ */ new Set([0, 1, 2, 3, 4, 5, 6]);
|
|
6488
6513
|
function decodeResponse(frame, expectedOpcode, hints = {}) {
|
|
6489
6514
|
if (frame.opcode !== expectedOpcode) {
|
|
6490
6515
|
throw new FerricStoreError(
|
|
@@ -6509,6 +6534,13 @@ function decodeResponse(frame, expectedOpcode, hints = {}) {
|
|
|
6509
6534
|
customPayload
|
|
6510
6535
|
);
|
|
6511
6536
|
if (status === STATUS_OK) return value;
|
|
6537
|
+
if (!KNOWN_NATIVE_RESPONSE_STATUSES.has(status)) {
|
|
6538
|
+
throw new FerricStoreError(`unknown native response status ${status}`, {
|
|
6539
|
+
raw: value,
|
|
6540
|
+
retryable: false,
|
|
6541
|
+
safeToRetry: false
|
|
6542
|
+
});
|
|
6543
|
+
}
|
|
6512
6544
|
const message = protocolErrorMessage(status, value);
|
|
6513
6545
|
throw classifyServerError(message, value, void 0, status);
|
|
6514
6546
|
}
|
|
@@ -6548,7 +6580,7 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
6548
6580
|
continue;
|
|
6549
6581
|
}
|
|
6550
6582
|
const error = classifyServerError(
|
|
6551
|
-
protocolErrorMessage(status
|
|
6583
|
+
protocolErrorMessage(pipelineStatusCode(status), payload),
|
|
6552
6584
|
payload,
|
|
6553
6585
|
void 0,
|
|
6554
6586
|
status
|
|
@@ -6557,15 +6589,46 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
6557
6589
|
out[index] = error;
|
|
6558
6590
|
continue;
|
|
6559
6591
|
}
|
|
6592
|
+
if (pipelineStatusToken(item[0]) != null) {
|
|
6593
|
+
const unknown = pipelineStatusToken(item[0]) ?? "unknown";
|
|
6594
|
+
const error = new FerricStoreError(`unknown native pipeline status ${JSON.stringify(unknown)}`, {
|
|
6595
|
+
raw: item,
|
|
6596
|
+
retryable: false,
|
|
6597
|
+
safeToRetry: false
|
|
6598
|
+
});
|
|
6599
|
+
if (options.throwOnItemError !== false) throw error;
|
|
6600
|
+
out[index] = error;
|
|
6601
|
+
continue;
|
|
6602
|
+
}
|
|
6560
6603
|
}
|
|
6561
6604
|
out[index] = item;
|
|
6562
6605
|
}
|
|
6563
6606
|
return out;
|
|
6564
6607
|
}
|
|
6565
6608
|
function pipelineStatus(value) {
|
|
6609
|
+
const status = pipelineStatusToken(value);
|
|
6610
|
+
if (status == null) return null;
|
|
6611
|
+
return status === "ok" || status === "error" || status === "auth" || status === "noperm" || status === "busy" || status === "reroute" || status === "bad_request" ? status : null;
|
|
6612
|
+
}
|
|
6613
|
+
function pipelineStatusToken(value) {
|
|
6566
6614
|
if (typeof value !== "string" && !Buffer26.isBuffer(value) && !(value instanceof Uint8Array)) return null;
|
|
6567
|
-
|
|
6568
|
-
|
|
6615
|
+
return asText(value).toLowerCase();
|
|
6616
|
+
}
|
|
6617
|
+
function pipelineStatusCode(status) {
|
|
6618
|
+
switch (status) {
|
|
6619
|
+
case "error":
|
|
6620
|
+
return 1;
|
|
6621
|
+
case "auth":
|
|
6622
|
+
return 2;
|
|
6623
|
+
case "noperm":
|
|
6624
|
+
return 3;
|
|
6625
|
+
case "busy":
|
|
6626
|
+
return 4;
|
|
6627
|
+
case "reroute":
|
|
6628
|
+
return 5;
|
|
6629
|
+
case "bad_request":
|
|
6630
|
+
return 6;
|
|
6631
|
+
}
|
|
6569
6632
|
}
|
|
6570
6633
|
function decodeResponseValue(opcode, body, hints, allowCompact, customPayload) {
|
|
6571
6634
|
if (customPayload && allowCompact) {
|
|
@@ -8225,6 +8288,22 @@ function plainRecord(value) {
|
|
|
8225
8288
|
return value;
|
|
8226
8289
|
}
|
|
8227
8290
|
|
|
8291
|
+
// src/native-command-preparation.ts
|
|
8292
|
+
function prepareNativeCommand(args, maxFrameBytes) {
|
|
8293
|
+
try {
|
|
8294
|
+
return buildProtocolCommand(args, maxFrameBytes);
|
|
8295
|
+
} catch (error) {
|
|
8296
|
+
throw requestNotSentError(error);
|
|
8297
|
+
}
|
|
8298
|
+
}
|
|
8299
|
+
function encodeNativeRequest(command, requestId, maxFrameBytes) {
|
|
8300
|
+
try {
|
|
8301
|
+
return encodeRequest(command, requestId, maxFrameBytes);
|
|
8302
|
+
} catch (error) {
|
|
8303
|
+
throw requestNotSentError(error);
|
|
8304
|
+
}
|
|
8305
|
+
}
|
|
8306
|
+
|
|
8228
8307
|
// src/native-adapter.ts
|
|
8229
8308
|
var NativeAdapter = class _NativeAdapter {
|
|
8230
8309
|
socket;
|
|
@@ -8332,15 +8411,13 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
8332
8411
|
return await this.executeCommandArgs(args);
|
|
8333
8412
|
}
|
|
8334
8413
|
async executeCommandArgs(args) {
|
|
8335
|
-
const command =
|
|
8414
|
+
const command = prepareNativeCommand(args, this.capabilities.requestFrameBytes);
|
|
8336
8415
|
return await this.request(command);
|
|
8337
8416
|
}
|
|
8338
8417
|
/** @internal Execute raw command arguments on a topology-selected lane. */
|
|
8339
8418
|
async executeCommandOnLane(args, laneId) {
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
laneId
|
|
8343
|
-
);
|
|
8419
|
+
const command = prepareNativeCommand(args, this.capabilities.requestFrameBytes);
|
|
8420
|
+
return await this.executeProtocolCommand(command, laneId);
|
|
8344
8421
|
}
|
|
8345
8422
|
async executeProtocolCommand(command, laneId) {
|
|
8346
8423
|
return await this.request(laneId == null ? command : { ...command, laneId });
|
|
@@ -8434,14 +8511,14 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
8434
8511
|
let frame;
|
|
8435
8512
|
try {
|
|
8436
8513
|
requestId = this.requestScheduler.nextRequestId();
|
|
8437
|
-
frame =
|
|
8514
|
+
frame = encodeNativeRequest(
|
|
8438
8515
|
withFlowQueryDeadline(command, timeoutMs),
|
|
8439
8516
|
requestId,
|
|
8440
8517
|
this.capabilities.requestFrameBytes
|
|
8441
8518
|
);
|
|
8442
8519
|
} catch (error) {
|
|
8443
8520
|
if (hasFlowControlCredit) this.flowControl.release(laneId);
|
|
8444
|
-
return Promise.reject(error instanceof Error ? error :
|
|
8521
|
+
return Promise.reject(error instanceof Error ? error : requestNotSentError(error));
|
|
8445
8522
|
}
|
|
8446
8523
|
return new Promise((resolve, reject) => {
|
|
8447
8524
|
const timer = timeoutMs == null ? void 0 : setLongTimeout(() => {
|
|
@@ -9016,12 +9093,16 @@ var HTTPTransport = class {
|
|
|
9016
9093
|
#requests = /* @__PURE__ */ new Set();
|
|
9017
9094
|
#closed = false;
|
|
9018
9095
|
async post(body, timeoutMs) {
|
|
9019
|
-
if (this.#closed)
|
|
9096
|
+
if (this.#closed) {
|
|
9097
|
+
throw new HTTPTransportError("HTTP transport is closed", { requestDisposition: "unsent" });
|
|
9098
|
+
}
|
|
9020
9099
|
const controller = new AbortController();
|
|
9021
9100
|
this.#requests.add(controller);
|
|
9022
9101
|
const timer = timeoutMs == null ? void 0 : setLongTimeout(() => controller.abort(requestTimeoutReason), timeoutMs);
|
|
9023
9102
|
timer?.unref();
|
|
9024
9103
|
try {
|
|
9104
|
+
const response = await this.request(this.config.commandUrl, "POST", body, 0, controller.signal);
|
|
9105
|
+
if (response.status !== 401 || this.config.headers.authorization == null) return response;
|
|
9025
9106
|
return await this.request(this.config.commandUrl, "POST", body, 0, controller.signal);
|
|
9026
9107
|
} catch (error) {
|
|
9027
9108
|
if (controller.signal.aborted) {
|
|
@@ -9031,9 +9112,22 @@ var HTTPTransport = class {
|
|
|
9031
9112
|
raw: { retryable: true, safe_to_retry: false }
|
|
9032
9113
|
});
|
|
9033
9114
|
}
|
|
9034
|
-
if (error instanceof
|
|
9115
|
+
if (error instanceof RequestTimeoutError) throw error;
|
|
9116
|
+
if (error instanceof HTTPTransportError) {
|
|
9117
|
+
if (error.requestDisposition != null) throw error;
|
|
9118
|
+
throw new HTTPTransportError(error.message, {
|
|
9119
|
+
cause: error.cause ?? error,
|
|
9120
|
+
raw: error.raw,
|
|
9121
|
+
requestDisposition: "possibly_sent",
|
|
9122
|
+
retryAfterMs: error.retryAfterMs,
|
|
9123
|
+
retryable: error.retryable,
|
|
9124
|
+
safeToRetry: false,
|
|
9125
|
+
statusCode: error.statusCode
|
|
9126
|
+
});
|
|
9127
|
+
}
|
|
9035
9128
|
throw new HTTPTransportError("HTTP command request failed", {
|
|
9036
9129
|
cause: error,
|
|
9130
|
+
requestDisposition: "possibly_sent",
|
|
9037
9131
|
retryable: true,
|
|
9038
9132
|
safeToRetry: false
|
|
9039
9133
|
});
|
|
@@ -9045,7 +9139,9 @@ var HTTPTransport = class {
|
|
|
9045
9139
|
async close() {
|
|
9046
9140
|
if (this.#closed) return;
|
|
9047
9141
|
this.#closed = true;
|
|
9048
|
-
const error = new HTTPTransportError("HTTP transport is closed"
|
|
9142
|
+
const error = new HTTPTransportError("HTTP transport is closed", {
|
|
9143
|
+
requestDisposition: "possibly_sent"
|
|
9144
|
+
});
|
|
9049
9145
|
for (const controller of this.#requests) controller.abort(error);
|
|
9050
9146
|
this.#httpAgent.destroy();
|
|
9051
9147
|
this.#httpsAgent.destroy();
|
|
@@ -9288,16 +9384,22 @@ var HTTPAdapter = class _HTTPAdapter {
|
|
|
9288
9384
|
await this.#transport.close();
|
|
9289
9385
|
}
|
|
9290
9386
|
async executeBatch(commands) {
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9387
|
+
let body;
|
|
9388
|
+
let serverBlockMs;
|
|
9389
|
+
try {
|
|
9390
|
+
if (commands.length > this.#config.maxBatchItems) {
|
|
9391
|
+
throw new HTTPTransportError("HTTP command batch exceeds maxBatchItems");
|
|
9392
|
+
}
|
|
9393
|
+
for (const command of commands) assertHTTPCommandSupported(command[0]);
|
|
9394
|
+
const prepared = commands.map((command) => prepareHTTPCommand(command, this.#config.maxRequestBytes));
|
|
9395
|
+
body = encodeHTTPCommands(prepared.map((command) => command.encoded), this.#config.maxRequestBytes);
|
|
9396
|
+
if (body.byteLength > this.#config.maxRequestBytes) {
|
|
9397
|
+
throw new HTTPTransportError("HTTP command request exceeds maxRequestBytes");
|
|
9398
|
+
}
|
|
9399
|
+
serverBlockMs = combinedServerBlockMs(prepared.map((command) => command.serverBlockMs));
|
|
9400
|
+
} catch (error) {
|
|
9401
|
+
throw unsentHTTPError(error);
|
|
9299
9402
|
}
|
|
9300
|
-
const serverBlockMs = combinedServerBlockMs(prepared.map((command) => command.serverBlockMs));
|
|
9301
9403
|
const response = await this.#transport.post(
|
|
9302
9404
|
body,
|
|
9303
9405
|
serverResponseTimeoutMs(this.#config.timeoutMs, serverBlockMs)
|
|
@@ -9354,16 +9456,32 @@ function commandError(value) {
|
|
|
9354
9456
|
}
|
|
9355
9457
|
function topLevelError(status, envelope, retryAfter) {
|
|
9356
9458
|
const details = isRecord2(envelope.error) ? envelope.error : {};
|
|
9459
|
+
const code = typeof details.code === "string" ? details.code.toLowerCase() : void 0;
|
|
9357
9460
|
const message = typeof details.message === "string" ? details.message : `HTTP command request failed with status ${status}`;
|
|
9358
9461
|
const retryAfterMs2 = retryAfterMilliseconds(retryAfter);
|
|
9462
|
+
const ambiguousTimeout = status === 408 || code === "request_timeout";
|
|
9463
|
+
const safeToRetry = !ambiguousTimeout && (details.safe_to_retry === true || definitelyRejectedHTTPStatus(status));
|
|
9359
9464
|
return new HTTPTransportError(message, {
|
|
9360
9465
|
raw: details,
|
|
9361
9466
|
retryable: status === 408 || status === 425 || status === 429 || status >= 500,
|
|
9362
9467
|
retryAfterMs: retryAfterMs2,
|
|
9363
|
-
|
|
9468
|
+
requestDisposition: "possibly_sent",
|
|
9469
|
+
safeToRetry,
|
|
9364
9470
|
statusCode: status
|
|
9365
9471
|
});
|
|
9366
9472
|
}
|
|
9473
|
+
function definitelyRejectedHTTPStatus(status) {
|
|
9474
|
+
return status === 400 || status === 401 || status === 403 || status === 404 || status === 405 || status === 406 || status === 411 || status === 413 || status === 414 || status === 415 || status === 422 || status === 426 || status === 431;
|
|
9475
|
+
}
|
|
9476
|
+
function unsentHTTPError(error) {
|
|
9477
|
+
if (error instanceof HTTPTransportError && error.requestDisposition === "unsent") return error;
|
|
9478
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
9479
|
+
return new HTTPTransportError(message, {
|
|
9480
|
+
cause: error,
|
|
9481
|
+
raw: error instanceof FerricStoreError ? error.raw ?? error : error,
|
|
9482
|
+
requestDisposition: "unsent"
|
|
9483
|
+
});
|
|
9484
|
+
}
|
|
9367
9485
|
function retryAfterMilliseconds(value) {
|
|
9368
9486
|
if (value == null) return void 0;
|
|
9369
9487
|
if (/^\d+$/u.test(value)) {
|
|
@@ -9456,9 +9574,9 @@ var ReconnectingExecutor = class {
|
|
|
9456
9574
|
const snapshot = snapshotPipelineCommands(commands);
|
|
9457
9575
|
const snapshotOptions = snapshotPipelineOptions(options) ?? {};
|
|
9458
9576
|
for (const command of snapshot) assertCommandHasStableConnectionState(command);
|
|
9459
|
-
if (this.closed) throw new
|
|
9577
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9460
9578
|
const initialExecutor = await this.executorPromise;
|
|
9461
|
-
if (this.closed) throw new
|
|
9579
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9462
9580
|
if (initialExecutor.executePipeline == null) {
|
|
9463
9581
|
return await executeCommandArraysIndividually(
|
|
9464
9582
|
async (command) => await this.executeCommandArgs(command),
|
|
@@ -9479,9 +9597,9 @@ var ReconnectingExecutor = class {
|
|
|
9479
9597
|
const snapshot = snapshotPipelineCommands(commands);
|
|
9480
9598
|
const snapshotOptions = snapshotPipelineOptions(options) ?? {};
|
|
9481
9599
|
for (const command of snapshot) assertCommandHasStableConnectionState(command);
|
|
9482
|
-
if (this.closed) throw new
|
|
9600
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9483
9601
|
const initialExecutor = await this.executorPromise;
|
|
9484
|
-
if (this.closed) throw new
|
|
9602
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9485
9603
|
if (initialExecutor.executeFusedPipeline == null) return void 0;
|
|
9486
9604
|
try {
|
|
9487
9605
|
return await initialExecutor.executeFusedPipeline(snapshot, snapshotOptions);
|
|
@@ -9514,7 +9632,7 @@ var ReconnectingExecutor = class {
|
|
|
9514
9632
|
return;
|
|
9515
9633
|
}
|
|
9516
9634
|
this.closed = true;
|
|
9517
|
-
this.retryAbortController.abort(new
|
|
9635
|
+
this.retryAbortController.abort(new RequestNotSentError("FerricStore client is closed"));
|
|
9518
9636
|
const executorPromise = this.executorPromise;
|
|
9519
9637
|
const reconnectPromise = this.reconnectPromise;
|
|
9520
9638
|
this.closePromise = (async () => {
|
|
@@ -9536,7 +9654,7 @@ var ReconnectingExecutor = class {
|
|
|
9536
9654
|
let executor = await this.executorPromise;
|
|
9537
9655
|
let retries = 0;
|
|
9538
9656
|
for (; ; ) {
|
|
9539
|
-
if (this.closed) throw new
|
|
9657
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9540
9658
|
try {
|
|
9541
9659
|
return await operation(executor);
|
|
9542
9660
|
} catch (error) {
|
|
@@ -9565,17 +9683,17 @@ var ReconnectingExecutor = class {
|
|
|
9565
9683
|
try {
|
|
9566
9684
|
await sleep(Math.min(this.maxDelayMs, base + jitter), this.retryAbortController.signal);
|
|
9567
9685
|
} catch (error) {
|
|
9568
|
-
if (this.closed) throw new
|
|
9686
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed", { cause: error });
|
|
9569
9687
|
throw error;
|
|
9570
9688
|
}
|
|
9571
9689
|
}
|
|
9572
9690
|
async reconnect(staleExecutor) {
|
|
9573
|
-
if (this.closed) throw new
|
|
9691
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9574
9692
|
const competingReconnect = this.reconnectPromise;
|
|
9575
9693
|
if (competingReconnect != null) return await competingReconnect;
|
|
9576
9694
|
const observedExecutorPromise = this.executorPromise;
|
|
9577
9695
|
const currentExecutor = await observedExecutorPromise.catch(() => void 0);
|
|
9578
|
-
if (this.closed) throw new
|
|
9696
|
+
if (this.closed) throw new RequestNotSentError("FerricStore client is closed");
|
|
9579
9697
|
if (this.reconnectPromise != null) return await this.reconnectPromise;
|
|
9580
9698
|
if (this.executorPromise !== observedExecutorPromise) return await this.executorPromise;
|
|
9581
9699
|
if (currentExecutor != null && currentExecutor !== staleExecutor) return currentExecutor;
|
|
@@ -9584,7 +9702,7 @@ var ReconnectingExecutor = class {
|
|
|
9584
9702
|
const nextExecutor = await this.createExecutor(this.retryAbortController.signal);
|
|
9585
9703
|
if (this.closed) {
|
|
9586
9704
|
await Promise.resolve(nextExecutor.close?.()).catch(() => void 0);
|
|
9587
|
-
throw new
|
|
9705
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
9588
9706
|
}
|
|
9589
9707
|
this.executorPromise = Promise.resolve(nextExecutor);
|
|
9590
9708
|
return nextExecutor;
|
|
@@ -10994,7 +11112,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
10994
11112
|
);
|
|
10995
11113
|
}
|
|
10996
11114
|
assertOpen() {
|
|
10997
|
-
if (this.closed) throw new
|
|
11115
|
+
if (this.closed) throw new RequestNotSentError("FerricStore topology adapter pool is closed");
|
|
10998
11116
|
}
|
|
10999
11117
|
};
|
|
11000
11118
|
|
|
@@ -12120,7 +12238,7 @@ var AutoBatchExecutor = class {
|
|
|
12120
12238
|
}
|
|
12121
12239
|
async executeCommandArgs(args) {
|
|
12122
12240
|
if (this.closed) {
|
|
12123
|
-
throw new
|
|
12241
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12124
12242
|
}
|
|
12125
12243
|
const command = snapshotCommandArguments(args);
|
|
12126
12244
|
if (this.executor.executePipeline == null) {
|
|
@@ -12140,7 +12258,7 @@ var AutoBatchExecutor = class {
|
|
|
12140
12258
|
if (orderingBarrier != null) {
|
|
12141
12259
|
await orderingBarrier;
|
|
12142
12260
|
if (this.closed) {
|
|
12143
|
-
throw new
|
|
12261
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12144
12262
|
}
|
|
12145
12263
|
}
|
|
12146
12264
|
return await new Promise((resolve, reject) => {
|
|
@@ -12154,7 +12272,7 @@ var AutoBatchExecutor = class {
|
|
|
12154
12272
|
}
|
|
12155
12273
|
async executePipeline(commands, options) {
|
|
12156
12274
|
if (this.closed) {
|
|
12157
|
-
throw new
|
|
12275
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12158
12276
|
}
|
|
12159
12277
|
const snapshot = snapshotPipelineCommands(commands);
|
|
12160
12278
|
const snapshotOptions = snapshotPipelineOptions(options);
|
|
@@ -12171,7 +12289,7 @@ var AutoBatchExecutor = class {
|
|
|
12171
12289
|
}
|
|
12172
12290
|
async executeFusedPipeline(commands, options) {
|
|
12173
12291
|
if (this.closed) {
|
|
12174
|
-
throw new
|
|
12292
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12175
12293
|
}
|
|
12176
12294
|
if (this.executor.executeFusedPipeline == null) return void 0;
|
|
12177
12295
|
const snapshot = snapshotPipelineCommands(commands);
|
|
@@ -12182,7 +12300,7 @@ var AutoBatchExecutor = class {
|
|
|
12182
12300
|
}
|
|
12183
12301
|
async refreshTopology() {
|
|
12184
12302
|
if (this.closed) {
|
|
12185
|
-
throw new
|
|
12303
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12186
12304
|
}
|
|
12187
12305
|
const refreshTopology = this.executor.refreshTopology?.bind(this.executor);
|
|
12188
12306
|
if (refreshTopology == null) {
|
|
@@ -12192,7 +12310,7 @@ var AutoBatchExecutor = class {
|
|
|
12192
12310
|
}
|
|
12193
12311
|
async route(key) {
|
|
12194
12312
|
if (this.closed) {
|
|
12195
|
-
throw new
|
|
12313
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12196
12314
|
}
|
|
12197
12315
|
const route = this.executor.route?.bind(this.executor);
|
|
12198
12316
|
if (route == null) {
|
|
@@ -12212,7 +12330,7 @@ var AutoBatchExecutor = class {
|
|
|
12212
12330
|
this.timer.cancel();
|
|
12213
12331
|
this.timer = void 0;
|
|
12214
12332
|
}
|
|
12215
|
-
this.failPending(new
|
|
12333
|
+
this.failPending(new RequestNotSentError("FerricStore client closed before auto-batch flush"));
|
|
12216
12334
|
await this.orderingBarrier;
|
|
12217
12335
|
await this.waitForInFlightBatches();
|
|
12218
12336
|
await Promise.allSettled([...this.inFlightHelpers]);
|
|
@@ -12222,7 +12340,7 @@ var AutoBatchExecutor = class {
|
|
|
12222
12340
|
}
|
|
12223
12341
|
async executeAfterPendingBatches(operation) {
|
|
12224
12342
|
if (this.closed) {
|
|
12225
|
-
throw new
|
|
12343
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12226
12344
|
}
|
|
12227
12345
|
const previousBarrier = this.orderingBarrier;
|
|
12228
12346
|
let releaseBarrier;
|
|
@@ -12243,7 +12361,7 @@ var AutoBatchExecutor = class {
|
|
|
12243
12361
|
}
|
|
12244
12362
|
executeHelper(operation) {
|
|
12245
12363
|
if (this.closed) {
|
|
12246
|
-
return Promise.reject(new
|
|
12364
|
+
return Promise.reject(new RequestNotSentError("FerricStore client is closed"));
|
|
12247
12365
|
}
|
|
12248
12366
|
const task = Promise.resolve().then(operation);
|
|
12249
12367
|
this.inFlightHelpers.add(task);
|
|
@@ -12265,7 +12383,7 @@ var AutoBatchExecutor = class {
|
|
|
12265
12383
|
await previousBarrier;
|
|
12266
12384
|
await this.flushNow();
|
|
12267
12385
|
if (this.closed) {
|
|
12268
|
-
throw new
|
|
12386
|
+
throw new RequestNotSentError("FerricStore client is closed");
|
|
12269
12387
|
}
|
|
12270
12388
|
dispatched = operation();
|
|
12271
12389
|
} finally {
|
|
@@ -14604,7 +14722,7 @@ var FerricStoreClientBase = class {
|
|
|
14604
14722
|
return validatePipelineResponse(results, snapshot.length);
|
|
14605
14723
|
}
|
|
14606
14724
|
async close() {
|
|
14607
|
-
this.closeAbortController.abort(new
|
|
14725
|
+
this.closeAbortController.abort(new RequestNotSentError("FerricStore client is closed"));
|
|
14608
14726
|
this.closePromise ??= (async () => await this.executor.close?.())();
|
|
14609
14727
|
await this.closePromise;
|
|
14610
14728
|
}
|
|
@@ -17680,7 +17798,7 @@ async function executeProducerWriteWithBackpressure(execute, policy, signal) {
|
|
|
17680
17798
|
function throwIfClosed(signal) {
|
|
17681
17799
|
if (!signal.aborted) return;
|
|
17682
17800
|
if (signal.reason instanceof Error) throw signal.reason;
|
|
17683
|
-
throw new
|
|
17801
|
+
throw new RequestNotSentError("FerricStore client is closed", { raw: signal.reason });
|
|
17684
17802
|
}
|
|
17685
17803
|
|
|
17686
17804
|
// src/flow-policy.ts
|
|
@@ -18498,12 +18616,20 @@ var FerricStoreClaimClient = class extends FerricStoreMutationClient {
|
|
|
18498
18616
|
return this.records(items);
|
|
18499
18617
|
}
|
|
18500
18618
|
async claimJobs(type, options) {
|
|
18501
|
-
|
|
18619
|
+
const requestedState = options.state;
|
|
18620
|
+
const includeState = options.includeState ?? requestedState == null;
|
|
18621
|
+
const jobs = await this.claimDue(type, {
|
|
18502
18622
|
...options,
|
|
18503
|
-
includeState
|
|
18623
|
+
includeState,
|
|
18504
18624
|
jobOnly: true,
|
|
18505
18625
|
limit: options.limit ?? 100
|
|
18506
18626
|
});
|
|
18627
|
+
if (!includeState && requestedState != null) {
|
|
18628
|
+
for (const job of jobs) {
|
|
18629
|
+
if (job[CLAIMED_ITEM_WIRE] != null) job.runState ??= requestedState;
|
|
18630
|
+
}
|
|
18631
|
+
}
|
|
18632
|
+
return jobs;
|
|
18507
18633
|
}
|
|
18508
18634
|
async reclaim(type, options) {
|
|
18509
18635
|
const captured = snapshotClaimOptions(options);
|
|
@@ -18526,7 +18652,7 @@ var FerricStoreClaimClient = class extends FerricStoreMutationClient {
|
|
|
18526
18652
|
this.appendPartitionOptions(args, captured);
|
|
18527
18653
|
append(args, "PRIORITY", captured.priority);
|
|
18528
18654
|
if (jobOnly) {
|
|
18529
|
-
append(args, "RETURN", compactClaimReturnMode2(
|
|
18655
|
+
append(args, "RETURN", compactClaimReturnMode2(true, captured.includeAttributes === true));
|
|
18530
18656
|
}
|
|
18531
18657
|
appendPayloadRead(args, captured.payload, captured.payloadMaxBytes);
|
|
18532
18658
|
appendValueReturn(args, { values: captured.values, valueMaxBytes: captured.valueMaxBytes });
|
|
@@ -18907,6 +19033,291 @@ var FerricStoreProducerClient = class extends FerricStoreClaimClient {
|
|
|
18907
19033
|
}
|
|
18908
19034
|
};
|
|
18909
19035
|
|
|
19036
|
+
// src/client-durable-step.ts
|
|
19037
|
+
import { createHash as createHash2 } from "crypto";
|
|
19038
|
+
|
|
19039
|
+
// src/workflow-utilities.ts
|
|
19040
|
+
function resolveWorkflowStates(configured, registrationFor) {
|
|
19041
|
+
const stateNames = [...new Set(configured)];
|
|
19042
|
+
if (stateNames.length === 0) throw new Error("Workflow worker requires at least one state");
|
|
19043
|
+
return stateNames.map((stateName) => {
|
|
19044
|
+
const registration = registrationFor(stateName);
|
|
19045
|
+
if (registration == null) {
|
|
19046
|
+
throw new Error(`No handler registered for workflow state '${stateName}'`);
|
|
19047
|
+
}
|
|
19048
|
+
return { registration, stateName };
|
|
19049
|
+
});
|
|
19050
|
+
}
|
|
19051
|
+
function normalizeStateMode(mode) {
|
|
19052
|
+
if (mode === "fifo" || mode === "parallel") return mode;
|
|
19053
|
+
throw new Error("state mode must be 'fifo' or 'parallel'");
|
|
19054
|
+
}
|
|
19055
|
+
function valueRefToString(value) {
|
|
19056
|
+
if (typeof value === "string") return value;
|
|
19057
|
+
if (Buffer.isBuffer(value)) return value.toString("utf8");
|
|
19058
|
+
if (typeof value === "object" && value != null && Object.hasOwn(value, "ref")) {
|
|
19059
|
+
const ref = value.ref;
|
|
19060
|
+
return typeof ref === "string" ? ref : Buffer.isBuffer(ref) ? ref.toString("utf8") : void 0;
|
|
19061
|
+
}
|
|
19062
|
+
return void 0;
|
|
19063
|
+
}
|
|
19064
|
+
|
|
19065
|
+
// src/client-durable-step.ts
|
|
19066
|
+
var DURABLE_STEP_VALUE_PREFIX = "__ferricstore_step__:sha256:";
|
|
19067
|
+
function durableMutationMayHaveCommitted(error) {
|
|
19068
|
+
if (error instanceof ConnectionClosedError || error instanceof RequestTimeoutError) {
|
|
19069
|
+
return error.requestDisposition === "possibly_sent";
|
|
19070
|
+
}
|
|
19071
|
+
if (error instanceof HTTPTransportError) return error.safeToRetry !== true;
|
|
19072
|
+
if (error instanceof FlowNotFoundError || error instanceof FlowWrongStateError || error instanceof InvalidCommandError || error instanceof StaleLeaseError) {
|
|
19073
|
+
return false;
|
|
19074
|
+
}
|
|
19075
|
+
if (error instanceof FerricStoreError && error.safeToRetry === true) return false;
|
|
19076
|
+
return true;
|
|
19077
|
+
}
|
|
19078
|
+
async function advanceClaim(client, job, options) {
|
|
19079
|
+
assertDurableClaim(job);
|
|
19080
|
+
assertNonEmptyString(options.toState, "toState");
|
|
19081
|
+
const partitionKey = job.partitionKey === "" ? void 0 : job.partitionKey;
|
|
19082
|
+
const response = await client.stepContinue(job.id, {
|
|
19083
|
+
attributesDelete: options.attributesDelete,
|
|
19084
|
+
attributesMerge: options.attributesMerge,
|
|
19085
|
+
dropValues: options.dropValues,
|
|
19086
|
+
fencingToken: job.fencingToken,
|
|
19087
|
+
fromState: job.runState,
|
|
19088
|
+
leaseMs: options.leaseMs,
|
|
19089
|
+
leaseToken: job.leaseToken,
|
|
19090
|
+
nowMs: options.nowMs,
|
|
19091
|
+
overrideValues: options.overrideValues,
|
|
19092
|
+
partitionKey,
|
|
19093
|
+
payload: options.payload,
|
|
19094
|
+
returnJob: true,
|
|
19095
|
+
stateMeta: options.stateMeta,
|
|
19096
|
+
type: job.type,
|
|
19097
|
+
toState: options.toState,
|
|
19098
|
+
valueRefs: options.valueRefs,
|
|
19099
|
+
values: options.values
|
|
19100
|
+
});
|
|
19101
|
+
const refreshed = response;
|
|
19102
|
+
if (refreshed[CLAIMED_ITEM_WIRE] != null) {
|
|
19103
|
+
if (refreshed.runState != null && refreshed.runState !== options.toState) {
|
|
19104
|
+
throw new FerricStoreError("compact continuation response returned the wrong runState");
|
|
19105
|
+
}
|
|
19106
|
+
refreshed.runState ??= options.toState;
|
|
19107
|
+
if (refreshed.type == null && job.type != null) refreshed.type = job.type;
|
|
19108
|
+
}
|
|
19109
|
+
assertContinuationClaim(job, refreshed, options.toState);
|
|
19110
|
+
return refreshed;
|
|
19111
|
+
}
|
|
19112
|
+
async function runDurableStep(client, job, options, hooks = {}) {
|
|
19113
|
+
assertDurableClaim(job);
|
|
19114
|
+
const name = options.name;
|
|
19115
|
+
const run2 = options.run;
|
|
19116
|
+
const continuation = snapshotAdvanceOptions(options);
|
|
19117
|
+
assertNonEmptyString(name, "name");
|
|
19118
|
+
if (name.trim().length === 0) throw new TypeError("name must not be blank");
|
|
19119
|
+
if (!name.isWellFormed()) throw new TypeError("name must contain valid Unicode");
|
|
19120
|
+
assertNonEmptyString(continuation.toState, "toState");
|
|
19121
|
+
if (typeof run2 !== "function") throw new TypeError("run must be a function");
|
|
19122
|
+
const resultName = durableStepValueName(name);
|
|
19123
|
+
assertStepValueIsReserved(continuation, resultName);
|
|
19124
|
+
const leaseMs = continuation.leaseMs ?? 3e4;
|
|
19125
|
+
const partitionKey = job.partitionKey === "" ? void 0 : job.partitionKey;
|
|
19126
|
+
const validated = await client.extendLease(job.id, {
|
|
19127
|
+
fencingToken: job.fencingToken,
|
|
19128
|
+
leaseMs,
|
|
19129
|
+
leaseToken: job.leaseToken,
|
|
19130
|
+
nowMs: continuation.nowMs,
|
|
19131
|
+
partitionKey
|
|
19132
|
+
});
|
|
19133
|
+
assertValidatedLease(job, validated);
|
|
19134
|
+
if (validated.valueRefs != null && Object.hasOwn(validated.valueRefs, resultName)) {
|
|
19135
|
+
if (validated.runState !== continuation.toState) {
|
|
19136
|
+
throw new FerricStoreError("committed durable step result does not match the requested target state");
|
|
19137
|
+
}
|
|
19138
|
+
const ref = valueRefToString(validated.valueRefs[resultName]);
|
|
19139
|
+
if (ref == null) {
|
|
19140
|
+
throw new FerricStoreError("committed durable step result has invalid reference metadata");
|
|
19141
|
+
}
|
|
19142
|
+
const entry = (await valueMGetEntries(client, [ref]))[0];
|
|
19143
|
+
if (entry?.found !== true) {
|
|
19144
|
+
throw new FerricStoreError("committed durable step result is missing");
|
|
19145
|
+
}
|
|
19146
|
+
const replayedJob = claimedItemFromRecord(validated);
|
|
19147
|
+
notifyWithoutReplacingOutcome(hooks.replayed, replayedJob);
|
|
19148
|
+
return { job: replayedJob, result: entry.value };
|
|
19149
|
+
}
|
|
19150
|
+
const result = normalizeStepResult(client, await run2());
|
|
19151
|
+
await hooks.beforeCommit?.();
|
|
19152
|
+
let refreshed;
|
|
19153
|
+
try {
|
|
19154
|
+
refreshed = await advanceClaim(client, validated, {
|
|
19155
|
+
...continuation,
|
|
19156
|
+
leaseMs,
|
|
19157
|
+
values: { ...continuation.values, [resultName]: result }
|
|
19158
|
+
});
|
|
19159
|
+
} catch (error) {
|
|
19160
|
+
notifyWithoutReplacingOutcome(hooks.commitFailed, error);
|
|
19161
|
+
throw error;
|
|
19162
|
+
}
|
|
19163
|
+
notifyWithoutReplacingOutcome(hooks.committed, refreshed);
|
|
19164
|
+
return { job: refreshed, result };
|
|
19165
|
+
}
|
|
19166
|
+
function notifyWithoutReplacingOutcome(callback, value) {
|
|
19167
|
+
try {
|
|
19168
|
+
callback?.(value);
|
|
19169
|
+
} catch {
|
|
19170
|
+
}
|
|
19171
|
+
}
|
|
19172
|
+
function normalizeStepResult(client, value) {
|
|
19173
|
+
return client.codec.decode(client.codec.encode(value));
|
|
19174
|
+
}
|
|
19175
|
+
function durableStepValueName(name) {
|
|
19176
|
+
const digest = createHash2("sha256").update(name, "utf8").digest("hex");
|
|
19177
|
+
return `${DURABLE_STEP_VALUE_PREFIX}${digest}`;
|
|
19178
|
+
}
|
|
19179
|
+
function snapshotAdvanceOptions(options) {
|
|
19180
|
+
return {
|
|
19181
|
+
...options.attributesDelete == null ? {} : { attributesDelete: [...options.attributesDelete] },
|
|
19182
|
+
...options.attributesMerge == null ? {} : { attributesMerge: { ...options.attributesMerge } },
|
|
19183
|
+
...options.dropValues == null ? {} : { dropValues: [...options.dropValues] },
|
|
19184
|
+
...options.leaseMs == null ? {} : { leaseMs: options.leaseMs },
|
|
19185
|
+
...options.nowMs == null ? {} : { nowMs: options.nowMs },
|
|
19186
|
+
...options.overrideValues == null ? {} : { overrideValues: [...options.overrideValues] },
|
|
19187
|
+
...options.payload === void 0 ? {} : { payload: options.payload },
|
|
19188
|
+
...options.stateMeta == null ? {} : { stateMeta: { ...options.stateMeta } },
|
|
19189
|
+
toState: options.toState,
|
|
19190
|
+
...options.valueRefs == null ? {} : { valueRefs: { ...options.valueRefs } },
|
|
19191
|
+
...options.values == null ? {} : { values: { ...options.values } }
|
|
19192
|
+
};
|
|
19193
|
+
}
|
|
19194
|
+
function assertDurableClaim(job) {
|
|
19195
|
+
if (typeof job !== "object" || job == null) throw new TypeError("job must be a claimed Flow");
|
|
19196
|
+
assertNonEmptyString(job.id, "job.id");
|
|
19197
|
+
assertNonEmptyString(job.runState, "job.runState");
|
|
19198
|
+
if (!Buffer.isBuffer(job.leaseToken) || job.leaseToken.byteLength === 0) {
|
|
19199
|
+
throw new TypeError("job.leaseToken must be a non-empty Buffer");
|
|
19200
|
+
}
|
|
19201
|
+
if ((typeof job.fencingToken !== "number" || !Number.isSafeInteger(job.fencingToken)) && typeof job.fencingToken !== "bigint") {
|
|
19202
|
+
throw new TypeError("job.fencingToken must be an integer");
|
|
19203
|
+
}
|
|
19204
|
+
if (fencingValue(job.fencingToken) <= 0n) {
|
|
19205
|
+
throw new TypeError("job.fencingToken must be a positive integer");
|
|
19206
|
+
}
|
|
19207
|
+
if (job.state !== "running") {
|
|
19208
|
+
throw new TypeError("job.state must be running");
|
|
19209
|
+
}
|
|
19210
|
+
}
|
|
19211
|
+
function assertValidatedLease(expected, actual) {
|
|
19212
|
+
try {
|
|
19213
|
+
assertDurableClaim(actual);
|
|
19214
|
+
} catch (error) {
|
|
19215
|
+
throw new FerricStoreError("lease validation returned an invalid claim", { cause: error });
|
|
19216
|
+
}
|
|
19217
|
+
if (actual.id !== expected.id) throw leaseValidationMismatch("id");
|
|
19218
|
+
if (normalizedPartition(actual.partitionKey) !== normalizedPartition(expected.partitionKey)) {
|
|
19219
|
+
throw leaseValidationMismatch("partition");
|
|
19220
|
+
}
|
|
19221
|
+
if (!actual.leaseToken.equals(expected.leaseToken)) throw leaseValidationMismatch("lease token");
|
|
19222
|
+
if (fencingValue(actual.fencingToken) !== fencingValue(expected.fencingToken)) {
|
|
19223
|
+
throw leaseValidationMismatch("fencing token");
|
|
19224
|
+
}
|
|
19225
|
+
if (actual.state !== expected.state) throw leaseValidationMismatch("physical state");
|
|
19226
|
+
if (actual.runState !== expected.runState) throw leaseValidationMismatch("runState");
|
|
19227
|
+
}
|
|
19228
|
+
function assertContinuationClaim(previous, refreshed, toState) {
|
|
19229
|
+
try {
|
|
19230
|
+
assertDurableClaim(refreshed);
|
|
19231
|
+
} catch (error) {
|
|
19232
|
+
throw new FerricStoreError("continuation response returned an invalid claim", { cause: error });
|
|
19233
|
+
}
|
|
19234
|
+
if (refreshed.id !== previous.id) throw continuationMismatch("id");
|
|
19235
|
+
if (normalizedPartition(refreshed.partitionKey) !== normalizedPartition(previous.partitionKey)) {
|
|
19236
|
+
throw continuationMismatch("partition");
|
|
19237
|
+
}
|
|
19238
|
+
if (refreshed.leaseToken.equals(previous.leaseToken)) {
|
|
19239
|
+
throw continuationMismatch("lease token did not change");
|
|
19240
|
+
}
|
|
19241
|
+
if (fencingValue(refreshed.fencingToken) <= fencingValue(previous.fencingToken)) {
|
|
19242
|
+
throw continuationMismatch("fencing token did not increase");
|
|
19243
|
+
}
|
|
19244
|
+
if (refreshed.state !== "running") throw continuationMismatch("physical state");
|
|
19245
|
+
if (refreshed.runState !== toState) throw continuationMismatch("runState");
|
|
19246
|
+
}
|
|
19247
|
+
function leaseValidationMismatch(field3) {
|
|
19248
|
+
return new FerricStoreError(`lease validation returned a mismatched ${field3}`);
|
|
19249
|
+
}
|
|
19250
|
+
function continuationMismatch(field3) {
|
|
19251
|
+
return new FerricStoreError(`continuation response returned a mismatched ${field3}`);
|
|
19252
|
+
}
|
|
19253
|
+
function normalizedPartition(value) {
|
|
19254
|
+
return value == null || value === "" ? void 0 : value;
|
|
19255
|
+
}
|
|
19256
|
+
function fencingValue(value) {
|
|
19257
|
+
return typeof value === "bigint" ? value : BigInt(value);
|
|
19258
|
+
}
|
|
19259
|
+
function assertNonEmptyString(value, name) {
|
|
19260
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
19261
|
+
throw new TypeError(`${name} must be a non-empty string`);
|
|
19262
|
+
}
|
|
19263
|
+
}
|
|
19264
|
+
function assertStepValueIsReserved(options, resultName) {
|
|
19265
|
+
if (options.values != null && Object.hasOwn(options.values, resultName)) {
|
|
19266
|
+
throw new TypeError("values cannot mutate the reserved durable step result");
|
|
19267
|
+
}
|
|
19268
|
+
if (options.valueRefs != null && Object.hasOwn(options.valueRefs, resultName)) {
|
|
19269
|
+
throw new TypeError("valueRefs cannot mutate the reserved durable step result");
|
|
19270
|
+
}
|
|
19271
|
+
if (options.dropValues?.includes(resultName) === true) {
|
|
19272
|
+
throw new TypeError("dropValues cannot mutate the reserved durable step result");
|
|
19273
|
+
}
|
|
19274
|
+
if (options.overrideValues?.includes(resultName) === true) {
|
|
19275
|
+
throw new TypeError("overrideValues cannot mutate the reserved durable step result");
|
|
19276
|
+
}
|
|
19277
|
+
}
|
|
19278
|
+
function claimedItemFromRecord(record) {
|
|
19279
|
+
return {
|
|
19280
|
+
...record.attributes == null ? {} : { attributes: record.attributes },
|
|
19281
|
+
fencingToken: record.fencingToken,
|
|
19282
|
+
id: record.id,
|
|
19283
|
+
leaseToken: Buffer.from(record.leaseToken),
|
|
19284
|
+
...record.partitionKey === "" ? {} : { partitionKey: record.partitionKey },
|
|
19285
|
+
...record.payload === void 0 ? {} : { payload: record.payload },
|
|
19286
|
+
...record.runState == null ? {} : { runState: record.runState },
|
|
19287
|
+
state: record.state,
|
|
19288
|
+
type: record.type
|
|
19289
|
+
};
|
|
19290
|
+
}
|
|
19291
|
+
|
|
19292
|
+
// src/client-step-continue.ts
|
|
19293
|
+
function stepContinueArguments(id, options, codec) {
|
|
19294
|
+
try {
|
|
19295
|
+
const args = [
|
|
19296
|
+
"FLOW.STEP_CONTINUE",
|
|
19297
|
+
id,
|
|
19298
|
+
options.leaseToken,
|
|
19299
|
+
options.fromState,
|
|
19300
|
+
options.toState,
|
|
19301
|
+
"FENCING",
|
|
19302
|
+
options.fencingToken,
|
|
19303
|
+
"LEASE_MS",
|
|
19304
|
+
options.leaseMs ?? 3e4,
|
|
19305
|
+
"NOW",
|
|
19306
|
+
options.nowMs ?? nowMs()
|
|
19307
|
+
];
|
|
19308
|
+
append(args, "PARTITION", options.partitionKey);
|
|
19309
|
+
append(args, "WORKER", options.worker);
|
|
19310
|
+
appendEncoded(args, "PAYLOAD", codec, options.payload);
|
|
19311
|
+
if (options.returnJob === true) args.push("RETURN", "JOBS_COMPACT");
|
|
19312
|
+
appendStateMeta(args, options.stateMeta);
|
|
19313
|
+
appendNamedValues(args, codec, options);
|
|
19314
|
+
appendAttributeMutations(args, options);
|
|
19315
|
+
return args;
|
|
19316
|
+
} catch (error) {
|
|
19317
|
+
throw requestNotSentError(error);
|
|
19318
|
+
}
|
|
19319
|
+
}
|
|
19320
|
+
|
|
18910
19321
|
// src/client.ts
|
|
18911
19322
|
var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClient {
|
|
18912
19323
|
static async fromUrl(url, options = {}) {
|
|
@@ -19021,33 +19432,30 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
19021
19432
|
appendNamedValues(args, this.codec, options);
|
|
19022
19433
|
return await this.recordOrGet(await this.commandArgs(args), id, partitionKey);
|
|
19023
19434
|
}
|
|
19435
|
+
/**
|
|
19436
|
+
* @deprecated Low-level compatibility API. Use {@link advance} for state-only
|
|
19437
|
+
* continuation or {@link step} for a durable closure.
|
|
19438
|
+
*/
|
|
19024
19439
|
async stepContinue(id, options) {
|
|
19025
19440
|
const partitionKey = options.partitionKey;
|
|
19026
19441
|
const returnJob = options.returnJob === true;
|
|
19027
19442
|
const type = options.type;
|
|
19028
|
-
const args =
|
|
19029
|
-
"FLOW.STEP_CONTINUE",
|
|
19030
|
-
id,
|
|
19031
|
-
options.leaseToken,
|
|
19032
|
-
options.fromState,
|
|
19033
|
-
options.toState,
|
|
19034
|
-
"FENCING",
|
|
19035
|
-
options.fencingToken,
|
|
19036
|
-
"LEASE_MS",
|
|
19037
|
-
options.leaseMs ?? 3e4,
|
|
19038
|
-
"NOW",
|
|
19039
|
-
options.nowMs ?? nowMs()
|
|
19040
|
-
];
|
|
19041
|
-
append(args, "PARTITION", partitionKey);
|
|
19042
|
-
append(args, "WORKER", options.worker);
|
|
19043
|
-
appendEncoded(args, "PAYLOAD", this.codec, options.payload);
|
|
19044
|
-
if (returnJob) args.push("RETURN", "JOBS_COMPACT");
|
|
19045
|
-
appendStateMeta(args, options.stateMeta);
|
|
19046
|
-
appendNamedValues(args, this.codec, options);
|
|
19047
|
-
appendAttributeMutations(args, options);
|
|
19443
|
+
const args = stepContinueArguments(id, options, this.codec);
|
|
19048
19444
|
const response = await this.commandArgs(args);
|
|
19049
19445
|
return returnJob ? claimedItemFromResp(response, this.codec, { type }) : await this.recordOrGet(response, id, partitionKey);
|
|
19050
19446
|
}
|
|
19447
|
+
/** Advance a claimed Flow and return its renewed claim. */
|
|
19448
|
+
async advance(job, options) {
|
|
19449
|
+
return await advanceClaim(this, job, options);
|
|
19450
|
+
}
|
|
19451
|
+
/**
|
|
19452
|
+
* Run a closure after validating the claim, then atomically journal its
|
|
19453
|
+
* result and advance the Flow. A committed result is replayed without
|
|
19454
|
+
* invoking the closure again.
|
|
19455
|
+
*/
|
|
19456
|
+
async step(job, options) {
|
|
19457
|
+
return await runDurableStep(this, job, options);
|
|
19458
|
+
}
|
|
19051
19459
|
async runStepsMany(items, options) {
|
|
19052
19460
|
if (items.length === 0) return Buffer.from("OK");
|
|
19053
19461
|
const hasStates = options.states != null;
|
|
@@ -19297,6 +19705,8 @@ function validateUnicodeScalarText2(value) {
|
|
|
19297
19705
|
|
|
19298
19706
|
// src/outcomes.ts
|
|
19299
19707
|
var OUTCOME_BRAND = /* @__PURE__ */ Symbol("ferricstore.outcome");
|
|
19708
|
+
var ALREADY_APPLIED_BRAND = /* @__PURE__ */ Symbol("ferricstore.alreadyApplied");
|
|
19709
|
+
var REPLAYED_STEP_BRAND = /* @__PURE__ */ Symbol("ferricstore.replayedStep");
|
|
19300
19710
|
function transition(toState, options = {}) {
|
|
19301
19711
|
return brandOutcome({ ...options, kind: "transition", toState });
|
|
19302
19712
|
}
|
|
@@ -19309,6 +19719,22 @@ function retry(options = {}) {
|
|
|
19309
19719
|
function fail2(options = {}) {
|
|
19310
19720
|
return brandOutcome({ ...options, kind: "fail" });
|
|
19311
19721
|
}
|
|
19722
|
+
function alreadyApplied(job) {
|
|
19723
|
+
return brandAlreadyApplied({ job, kind: "already_applied" });
|
|
19724
|
+
}
|
|
19725
|
+
function appliedStep(job, result) {
|
|
19726
|
+
return brandAlreadyApplied({ applied: true, job, kind: "already_applied", result });
|
|
19727
|
+
}
|
|
19728
|
+
function replayedStep(job, result) {
|
|
19729
|
+
const replayed = { applied: false, job, result };
|
|
19730
|
+
Object.defineProperty(replayed, REPLAYED_STEP_BRAND, {
|
|
19731
|
+
configurable: false,
|
|
19732
|
+
enumerable: false,
|
|
19733
|
+
value: true,
|
|
19734
|
+
writable: false
|
|
19735
|
+
});
|
|
19736
|
+
return replayed;
|
|
19737
|
+
}
|
|
19312
19738
|
function isOutcome(value) {
|
|
19313
19739
|
if (typeof value !== "object" || value == null || !Object.hasOwn(value, OUTCOME_BRAND) || value[OUTCOME_BRAND] !== true) {
|
|
19314
19740
|
return false;
|
|
@@ -19319,6 +19745,12 @@ function isOutcome(value) {
|
|
|
19319
19745
|
}
|
|
19320
19746
|
return outcome.kind === "complete" || outcome.kind === "retry" || outcome.kind === "fail";
|
|
19321
19747
|
}
|
|
19748
|
+
function isAlreadyAppliedOutcome(value) {
|
|
19749
|
+
return typeof value === "object" && value != null && Object.hasOwn(value, ALREADY_APPLIED_BRAND) && value[ALREADY_APPLIED_BRAND] === true && value.kind === "already_applied";
|
|
19750
|
+
}
|
|
19751
|
+
function isReplayedStepResult(value) {
|
|
19752
|
+
return typeof value === "object" && value != null && Object.hasOwn(value, REPLAYED_STEP_BRAND) && value[REPLAYED_STEP_BRAND] === true && value.applied === false;
|
|
19753
|
+
}
|
|
19322
19754
|
function brandOutcome(outcome) {
|
|
19323
19755
|
Object.defineProperty(outcome, "kind", {
|
|
19324
19756
|
configurable: false,
|
|
@@ -19342,6 +19774,21 @@ function brandOutcome(outcome) {
|
|
|
19342
19774
|
});
|
|
19343
19775
|
return outcome;
|
|
19344
19776
|
}
|
|
19777
|
+
function brandAlreadyApplied(outcome) {
|
|
19778
|
+
Object.defineProperty(outcome, "kind", {
|
|
19779
|
+
configurable: false,
|
|
19780
|
+
enumerable: true,
|
|
19781
|
+
value: "already_applied",
|
|
19782
|
+
writable: false
|
|
19783
|
+
});
|
|
19784
|
+
Object.defineProperty(outcome, ALREADY_APPLIED_BRAND, {
|
|
19785
|
+
configurable: false,
|
|
19786
|
+
enumerable: false,
|
|
19787
|
+
value: true,
|
|
19788
|
+
writable: false
|
|
19789
|
+
});
|
|
19790
|
+
return outcome;
|
|
19791
|
+
}
|
|
19345
19792
|
|
|
19346
19793
|
// src/worker-config.ts
|
|
19347
19794
|
function snapshotWorkerConfig(options) {
|
|
@@ -19358,8 +19805,7 @@ function snapshotWorkerConfig(options) {
|
|
|
19358
19805
|
return Object.freeze(snapshot);
|
|
19359
19806
|
}
|
|
19360
19807
|
|
|
19361
|
-
// src/worker-
|
|
19362
|
-
var DEFAULT_FLOW_MANY_BATCH_LIMIT2 = 1e3;
|
|
19808
|
+
// src/worker-lease-guard.ts
|
|
19363
19809
|
var LeaseRenewalError = class extends Error {
|
|
19364
19810
|
constructor(cause) {
|
|
19365
19811
|
super("FerricStore lease renewal failed", { cause });
|
|
@@ -19370,37 +19816,58 @@ var LeaseRenewalGuard = class {
|
|
|
19370
19816
|
constructor(client, leasedJob, leaseMs, options) {
|
|
19371
19817
|
this.client = client;
|
|
19372
19818
|
this.leaseMs = leaseMs;
|
|
19373
|
-
this.
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
|
|
19377
|
-
const intervalMs = positiveInteger4(options.leaseRenewIntervalMs, Math.max(1, Math.trunc(leaseMs / 2)));
|
|
19378
|
-
this.timer = setLongInterval(() => this.renew(), intervalMs);
|
|
19379
|
-
this.timer.unref();
|
|
19819
|
+
this.currentJob = snapshotLeasedJob(leasedJob);
|
|
19820
|
+
this.renewalEnabled = options.leaseRenewal !== false;
|
|
19821
|
+
this.intervalMs = positiveInteger4(options.leaseRenewIntervalMs, Math.max(1, Math.trunc(leaseMs / 2)));
|
|
19822
|
+
this.startRenewal();
|
|
19380
19823
|
}
|
|
19381
19824
|
client;
|
|
19382
19825
|
leaseMs;
|
|
19383
19826
|
error;
|
|
19384
19827
|
inFlight;
|
|
19385
|
-
|
|
19828
|
+
currentJob;
|
|
19829
|
+
intervalMs;
|
|
19830
|
+
renewalEnabled;
|
|
19831
|
+
state = "active";
|
|
19386
19832
|
timer;
|
|
19833
|
+
get job() {
|
|
19834
|
+
return this.currentJob;
|
|
19835
|
+
}
|
|
19387
19836
|
assertActive() {
|
|
19388
|
-
if (this.error != null)
|
|
19389
|
-
throw this.error;
|
|
19390
|
-
}
|
|
19837
|
+
if (this.error != null) throw this.error;
|
|
19391
19838
|
}
|
|
19392
19839
|
async stop() {
|
|
19393
|
-
|
|
19394
|
-
|
|
19395
|
-
|
|
19396
|
-
|
|
19840
|
+
this.state = "stopped";
|
|
19841
|
+
this.cancelRenewal();
|
|
19842
|
+
await this.inFlight;
|
|
19843
|
+
this.assertActive();
|
|
19844
|
+
}
|
|
19845
|
+
async pauseForLeaseMutation() {
|
|
19846
|
+
if (this.state === "stopped") throw new Error("lease renewal guard is stopped");
|
|
19847
|
+
if (this.state === "paused") return;
|
|
19848
|
+
this.state = "paused";
|
|
19849
|
+
this.cancelRenewal();
|
|
19397
19850
|
await this.inFlight;
|
|
19398
19851
|
this.assertActive();
|
|
19399
19852
|
}
|
|
19853
|
+
resumeWith(job) {
|
|
19854
|
+
if (this.state !== "paused") throw new Error("lease renewal guard is not paused");
|
|
19855
|
+
this.currentJob = snapshotLeasedJob(job);
|
|
19856
|
+
this.state = "active";
|
|
19857
|
+
this.startRenewal();
|
|
19858
|
+
}
|
|
19859
|
+
cancelRenewal() {
|
|
19860
|
+
if (this.timer == null) return;
|
|
19861
|
+
this.timer.cancel();
|
|
19862
|
+
this.timer = void 0;
|
|
19863
|
+
}
|
|
19864
|
+
startRenewal() {
|
|
19865
|
+
if (!this.renewalEnabled || this.state !== "active") return;
|
|
19866
|
+
this.timer = setLongInterval(() => this.renew(), this.intervalMs);
|
|
19867
|
+
this.timer.unref();
|
|
19868
|
+
}
|
|
19400
19869
|
renew() {
|
|
19401
|
-
if (this.error != null || this.inFlight != null)
|
|
19402
|
-
return;
|
|
19403
|
-
}
|
|
19870
|
+
if (this.state !== "active" || this.error != null || this.inFlight != null) return;
|
|
19404
19871
|
const renewal = this.client.extendLease(this.job.id, {
|
|
19405
19872
|
fencingToken: this.job.fencingToken,
|
|
19406
19873
|
leaseMs: this.leaseMs,
|
|
@@ -19411,17 +19878,12 @@ var LeaseRenewalGuard = class {
|
|
|
19411
19878
|
() => void 0,
|
|
19412
19879
|
(error) => {
|
|
19413
19880
|
this.error = new LeaseRenewalError(error);
|
|
19414
|
-
|
|
19415
|
-
this.timer.cancel();
|
|
19416
|
-
this.timer = void 0;
|
|
19417
|
-
}
|
|
19881
|
+
this.cancelRenewal();
|
|
19418
19882
|
}
|
|
19419
19883
|
);
|
|
19420
19884
|
this.inFlight = renewal;
|
|
19421
19885
|
void renewal.finally(() => {
|
|
19422
|
-
if (this.inFlight === renewal)
|
|
19423
|
-
this.inFlight = void 0;
|
|
19424
|
-
}
|
|
19886
|
+
if (this.inFlight === renewal) this.inFlight = void 0;
|
|
19425
19887
|
});
|
|
19426
19888
|
}
|
|
19427
19889
|
};
|
|
@@ -19445,8 +19907,14 @@ function snapshotLeasedJob(job) {
|
|
|
19445
19907
|
}
|
|
19446
19908
|
return snapshot;
|
|
19447
19909
|
}
|
|
19910
|
+
function positiveInteger4(value, fallback) {
|
|
19911
|
+
return value == null || !Number.isFinite(value) ? fallback : Math.max(1, Math.trunc(value));
|
|
19912
|
+
}
|
|
19913
|
+
|
|
19914
|
+
// src/worker-internal.ts
|
|
19915
|
+
var DEFAULT_FLOW_MANY_BATCH_LIMIT2 = 1e3;
|
|
19448
19916
|
function workerConcurrency(options) {
|
|
19449
|
-
return
|
|
19917
|
+
return positiveInteger5(options.concurrency ?? options.workers, 1);
|
|
19450
19918
|
}
|
|
19451
19919
|
function workerRefillStrategy(options) {
|
|
19452
19920
|
return options.refillStrategy === "wave" ? "wave" : "continuous";
|
|
@@ -19489,18 +19957,18 @@ function workerErrorPayload(error, options, codec) {
|
|
|
19489
19957
|
}
|
|
19490
19958
|
function workerBatchSize(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
|
|
19491
19959
|
return Math.min(
|
|
19492
|
-
|
|
19493
|
-
|
|
19960
|
+
positiveInteger5(options.batchSize, 10),
|
|
19961
|
+
positiveInteger5(flowManyBatchLimit, DEFAULT_FLOW_MANY_BATCH_LIMIT2)
|
|
19494
19962
|
);
|
|
19495
19963
|
}
|
|
19496
19964
|
function workerClaimLimit(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
|
|
19497
19965
|
return Math.min(workerBatchSize(options, flowManyBatchLimit), workerConcurrency(options));
|
|
19498
19966
|
}
|
|
19499
19967
|
function workerDrainBatches(options) {
|
|
19500
|
-
return
|
|
19968
|
+
return positiveInteger5(options.claimDrainBatches, 1);
|
|
19501
19969
|
}
|
|
19502
19970
|
function workerLeaseMs(options, fallback = 3e4) {
|
|
19503
|
-
return
|
|
19971
|
+
return positiveInteger5(options.leaseMs, positiveInteger5(fallback, 3e4));
|
|
19504
19972
|
}
|
|
19505
19973
|
function workerIdleSleepMs(options) {
|
|
19506
19974
|
return nonNegativeDuration(options.idleSleepMs, 250);
|
|
@@ -19512,7 +19980,7 @@ function workerClaimBlockMs(options, useBlocking) {
|
|
|
19512
19980
|
if (options.signal == null || !Number.isFinite(options.blockMs) || options.blockMs < 0) {
|
|
19513
19981
|
return options.blockMs;
|
|
19514
19982
|
}
|
|
19515
|
-
const abortPollMs =
|
|
19983
|
+
const abortPollMs = positiveInteger5(options.abortPollMs, 1e3);
|
|
19516
19984
|
return options.blockMs === 0 ? abortPollMs : Math.min(Math.trunc(options.blockMs), abortPollMs);
|
|
19517
19985
|
}
|
|
19518
19986
|
function workerMaxIdleSleepMs(options, idleSleepMs = workerIdleSleepMs(options)) {
|
|
@@ -19523,8 +19991,8 @@ function nextWorkerIdleSleepMs(currentIdleSleepMs, maxIdleSleepMs) {
|
|
|
19523
19991
|
return Math.min(maxIdleSleepMs, Math.max(1, currentIdleSleepMs * 2));
|
|
19524
19992
|
}
|
|
19525
19993
|
async function runContinuousWorkerPool(options) {
|
|
19526
|
-
const concurrency =
|
|
19527
|
-
const maxClaimSize =
|
|
19994
|
+
const concurrency = positiveInteger5(options.concurrency, 1);
|
|
19995
|
+
const maxClaimSize = positiveInteger5(options.maxClaimSize, concurrency);
|
|
19528
19996
|
const initialIdleSleepMs = nonNegativeDuration(options.idleSleepMs, 250);
|
|
19529
19997
|
const maxIdleSleepMs = Math.max(
|
|
19530
19998
|
initialIdleSleepMs,
|
|
@@ -19646,7 +20114,7 @@ function normalizeWorkflowWorkerConfig(options) {
|
|
|
19646
20114
|
...captured
|
|
19647
20115
|
});
|
|
19648
20116
|
}
|
|
19649
|
-
function
|
|
20117
|
+
function positiveInteger5(value, fallback) {
|
|
19650
20118
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(1, Math.trunc(value));
|
|
19651
20119
|
}
|
|
19652
20120
|
function nonNegativeInteger5(value, fallback) {
|
|
@@ -20588,51 +21056,57 @@ var Queue = class {
|
|
|
20588
21056
|
// src/workflow.ts
|
|
20589
21057
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
20590
21058
|
|
|
20591
|
-
// src/workflow-
|
|
20592
|
-
function
|
|
20593
|
-
const
|
|
20594
|
-
|
|
20595
|
-
|
|
20596
|
-
|
|
20597
|
-
|
|
20598
|
-
|
|
20599
|
-
|
|
20600
|
-
|
|
21059
|
+
// src/workflow-registration.ts
|
|
21060
|
+
function createWorkflowStateRegistration(name, handler, options, defaultValueMaxBytes) {
|
|
21061
|
+
const own2 = { ...options };
|
|
21062
|
+
const claimValues = own2.claimValues == null ? void 0 : snapshotOwnStringArray(own2.claimValues, "claimValues");
|
|
21063
|
+
const retryPolicy = own2.retryPolicy == null ? void 0 : Object.freeze({ ...own2.retryPolicy });
|
|
21064
|
+
return Object.freeze({
|
|
21065
|
+
claimPayload: own2.claimPayload ?? true,
|
|
21066
|
+
claimRecord: own2.claimRecord ?? true,
|
|
21067
|
+
exceptionPolicy: normalizeExceptionPolicy(own2.exceptionPolicy),
|
|
21068
|
+
handler,
|
|
21069
|
+
leaseMs: own2.leaseMs ?? 3e4,
|
|
21070
|
+
...own2.mode == null ? {} : { mode: normalizeStateMode(own2.mode) },
|
|
21071
|
+
name,
|
|
21072
|
+
returnRecord: own2.returnRecord ?? false,
|
|
21073
|
+
valueMaxBytes: own2.valueMaxBytes ?? defaultValueMaxBytes,
|
|
21074
|
+
...claimValues == null ? {} : { claimValues },
|
|
21075
|
+
...retryPolicy == null ? {} : { retryPolicy }
|
|
20601
21076
|
});
|
|
20602
21077
|
}
|
|
20603
|
-
function normalizeStateMode(mode) {
|
|
20604
|
-
if (mode === "fifo" || mode === "parallel") return mode;
|
|
20605
|
-
throw new Error("state mode must be 'fifo' or 'parallel'");
|
|
20606
|
-
}
|
|
20607
|
-
function valueRefToString(value) {
|
|
20608
|
-
if (typeof value === "string") return value;
|
|
20609
|
-
if (Buffer.isBuffer(value)) return value.toString("utf8");
|
|
20610
|
-
if (typeof value === "object" && value != null && Object.hasOwn(value, "ref")) {
|
|
20611
|
-
const ref = value.ref;
|
|
20612
|
-
return typeof ref === "string" ? ref : Buffer.isBuffer(ref) ? ref.toString("utf8") : void 0;
|
|
20613
|
-
}
|
|
20614
|
-
return void 0;
|
|
20615
|
-
}
|
|
20616
21078
|
|
|
20617
21079
|
// src/workflow-context.ts
|
|
20618
21080
|
var MISSING_VALUE = /* @__PURE__ */ Symbol("ferricstore.missingValue");
|
|
20619
21081
|
var WorkflowContext = class {
|
|
20620
21082
|
workflow;
|
|
20621
21083
|
job;
|
|
20622
|
-
stateName;
|
|
20623
21084
|
flow;
|
|
21085
|
+
appliedMutation = false;
|
|
21086
|
+
currentStateName;
|
|
20624
21087
|
leaseJob;
|
|
21088
|
+
mutationFailure;
|
|
21089
|
+
mutationPhase = "idle";
|
|
21090
|
+
mutationCoordinator;
|
|
20625
21091
|
valueCache = /* @__PURE__ */ new Map();
|
|
20626
|
-
constructor(workflow, job, stateName
|
|
21092
|
+
constructor(workflow, job, stateName) {
|
|
20627
21093
|
this.workflow = workflow;
|
|
20628
21094
|
this.job = job;
|
|
20629
|
-
this.leaseJob =
|
|
20630
|
-
this.
|
|
21095
|
+
this.leaseJob = job;
|
|
21096
|
+
this.currentStateName = stateName;
|
|
20631
21097
|
this.flow = new WorkflowFlowCommands(this);
|
|
20632
21098
|
}
|
|
21099
|
+
/** @internal */
|
|
21100
|
+
configureWorkerMutation(leaseJob, coordinator) {
|
|
21101
|
+
this.leaseJob = leaseJob;
|
|
21102
|
+
this.mutationCoordinator = coordinator;
|
|
21103
|
+
}
|
|
20633
21104
|
get client() {
|
|
20634
21105
|
return this.workflow.client;
|
|
20635
21106
|
}
|
|
21107
|
+
get stateName() {
|
|
21108
|
+
return this.currentStateName;
|
|
21109
|
+
}
|
|
20636
21110
|
get id() {
|
|
20637
21111
|
return this.leaseJob.id;
|
|
20638
21112
|
}
|
|
@@ -20643,7 +21117,7 @@ var WorkflowContext = class {
|
|
|
20643
21117
|
return this.leaseJob.state;
|
|
20644
21118
|
}
|
|
20645
21119
|
get logicalState() {
|
|
20646
|
-
return this.
|
|
21120
|
+
return this.currentStateName;
|
|
20647
21121
|
}
|
|
20648
21122
|
get partitionKey() {
|
|
20649
21123
|
return this.leaseJob.partitionKey;
|
|
@@ -20681,6 +21155,53 @@ var WorkflowContext = class {
|
|
|
20681
21155
|
get correlationId() {
|
|
20682
21156
|
return "correlationId" in this.job ? this.job.correlationId : void 0;
|
|
20683
21157
|
}
|
|
21158
|
+
async advance(toState, options = {}) {
|
|
21159
|
+
if (typeof toState !== "string" || toState.length === 0) {
|
|
21160
|
+
throw new TypeError("toState must be a non-empty string");
|
|
21161
|
+
}
|
|
21162
|
+
const current = this.durableClaim();
|
|
21163
|
+
await this.beforeCommit();
|
|
21164
|
+
let refreshed;
|
|
21165
|
+
try {
|
|
21166
|
+
refreshed = await advanceClaim(this.client, current, { ...options, toState });
|
|
21167
|
+
} catch (error) {
|
|
21168
|
+
this.commitFailed(error);
|
|
21169
|
+
throw error;
|
|
21170
|
+
}
|
|
21171
|
+
this.committed(refreshed);
|
|
21172
|
+
return alreadyApplied(refreshed);
|
|
21173
|
+
}
|
|
21174
|
+
async step(options) {
|
|
21175
|
+
let applied = false;
|
|
21176
|
+
const stepped = await runDurableStep(this.client, this.durableClaim(), options, {
|
|
21177
|
+
beforeCommit: async () => await this.beforeCommit(),
|
|
21178
|
+
commitFailed: (error) => this.commitFailed(error),
|
|
21179
|
+
committed: (job) => {
|
|
21180
|
+
applied = true;
|
|
21181
|
+
this.committed(job);
|
|
21182
|
+
},
|
|
21183
|
+
replayed: (job) => this.replayed(job)
|
|
21184
|
+
});
|
|
21185
|
+
return applied ? appliedStep(stepped.job, stepped.result) : replayedStep(stepped.job, stepped.result);
|
|
21186
|
+
}
|
|
21187
|
+
/** @internal */
|
|
21188
|
+
get hasAppliedMutation() {
|
|
21189
|
+
return this.appliedMutation;
|
|
21190
|
+
}
|
|
21191
|
+
/** @internal */
|
|
21192
|
+
get uncertainMutationFailure() {
|
|
21193
|
+
return this.mutationPhase === "uncertain" ? this.mutationFailure : void 0;
|
|
21194
|
+
}
|
|
21195
|
+
/** @internal */
|
|
21196
|
+
get hasUncertainMutation() {
|
|
21197
|
+
return this.mutationPhase === "uncertain";
|
|
21198
|
+
}
|
|
21199
|
+
/** @internal */
|
|
21200
|
+
assertAppliedOutcome(outcome) {
|
|
21201
|
+
if (!this.appliedMutation || !outcome.job.leaseToken.equals(this.leaseJob.leaseToken) || outcome.job.fencingToken !== this.leaseJob.fencingToken) {
|
|
21202
|
+
throw new Error("already-applied outcome does not match the workflow's refreshed claim");
|
|
21203
|
+
}
|
|
21204
|
+
}
|
|
20684
21205
|
async value(name, defaultValue, options = {}) {
|
|
20685
21206
|
const useLocalCache = options.localCache ?? this.workflow.valueConfig.localCache;
|
|
20686
21207
|
if (useLocalCache && this.valueCache.has(name)) {
|
|
@@ -20760,7 +21281,49 @@ var WorkflowContext = class {
|
|
|
20760
21281
|
return result;
|
|
20761
21282
|
}
|
|
20762
21283
|
valueMaxBytes() {
|
|
20763
|
-
return this.workflow.stateRegistration(this.
|
|
21284
|
+
return this.workflow.stateRegistration(this.currentStateName)?.valueMaxBytes;
|
|
21285
|
+
}
|
|
21286
|
+
durableClaim() {
|
|
21287
|
+
const runState = this.leaseJob.runState ?? (this.leaseJob[CLAIMED_ITEM_WIRE] == null ? void 0 : this.currentStateName);
|
|
21288
|
+
if (typeof runState !== "string" || runState.length === 0) {
|
|
21289
|
+
throw new TypeError("job.runState must be a non-empty string");
|
|
21290
|
+
}
|
|
21291
|
+
return {
|
|
21292
|
+
...this.leaseJob,
|
|
21293
|
+
leaseToken: Buffer.from(this.leaseJob.leaseToken),
|
|
21294
|
+
runState
|
|
21295
|
+
};
|
|
21296
|
+
}
|
|
21297
|
+
async beforeCommit() {
|
|
21298
|
+
if (this.mutationPhase !== "idle") {
|
|
21299
|
+
throw new Error("a durable workflow mutation is already in progress or has an uncertain result");
|
|
21300
|
+
}
|
|
21301
|
+
await this.mutationCoordinator?.pause();
|
|
21302
|
+
this.mutationPhase = "committing";
|
|
21303
|
+
}
|
|
21304
|
+
commitFailed(error) {
|
|
21305
|
+
if (!durableMutationMayHaveCommitted(error)) {
|
|
21306
|
+
this.mutationFailure = void 0;
|
|
21307
|
+
this.mutationPhase = "idle";
|
|
21308
|
+
this.mutationCoordinator?.resume(this.leaseJob);
|
|
21309
|
+
return;
|
|
21310
|
+
}
|
|
21311
|
+
this.mutationFailure = error;
|
|
21312
|
+
this.mutationPhase = "uncertain";
|
|
21313
|
+
}
|
|
21314
|
+
committed(job) {
|
|
21315
|
+
this.acceptJob(job);
|
|
21316
|
+
this.appliedMutation = true;
|
|
21317
|
+
this.mutationCoordinator?.resume(job);
|
|
21318
|
+
}
|
|
21319
|
+
replayed(job) {
|
|
21320
|
+
this.acceptJob(job);
|
|
21321
|
+
}
|
|
21322
|
+
acceptJob(job) {
|
|
21323
|
+
this.leaseJob = job;
|
|
21324
|
+
this.currentStateName = job.runState ?? this.currentStateName;
|
|
21325
|
+
this.mutationFailure = void 0;
|
|
21326
|
+
this.mutationPhase = "idle";
|
|
20764
21327
|
}
|
|
20765
21328
|
};
|
|
20766
21329
|
var WorkflowFlowCommands = class {
|
|
@@ -20798,6 +21361,7 @@ var WorkflowFlowCommands = class {
|
|
|
20798
21361
|
toState
|
|
20799
21362
|
});
|
|
20800
21363
|
}
|
|
21364
|
+
/** @deprecated Use `ctx.advance(toState)`. */
|
|
20801
21365
|
async stepContinue(toState, options = {}) {
|
|
20802
21366
|
return await this.ctx.client.stepContinue(this.ctx.id, {
|
|
20803
21367
|
...options,
|
|
@@ -20960,25 +21524,86 @@ async function applyFail(client, ctx, outcome, returnRecord) {
|
|
|
20960
21524
|
});
|
|
20961
21525
|
}
|
|
20962
21526
|
|
|
20963
|
-
// src/workflow-
|
|
20964
|
-
|
|
20965
|
-
|
|
20966
|
-
|
|
20967
|
-
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
|
|
20976
|
-
|
|
20977
|
-
|
|
20978
|
-
|
|
20979
|
-
|
|
21527
|
+
// src/workflow-worker-context.ts
|
|
21528
|
+
var WorkerWorkflowContext = class extends WorkflowContext {
|
|
21529
|
+
constructor(workflow, job, stateName, leaseJob, mutationCoordinator) {
|
|
21530
|
+
super(workflow, job, stateName);
|
|
21531
|
+
this.configureWorkerMutation(leaseJob, mutationCoordinator);
|
|
21532
|
+
}
|
|
21533
|
+
};
|
|
21534
|
+
|
|
21535
|
+
// src/workflow-job-execution.ts
|
|
21536
|
+
async function executeWorkflowJob(workflow, workerOptions, job, registration, guard) {
|
|
21537
|
+
guard.assertActive();
|
|
21538
|
+
const ctx = new WorkerWorkflowContext(workflow, job, registration.name, guard.job, {
|
|
21539
|
+
pause: async () => await guard.pauseForLeaseMutation(),
|
|
21540
|
+
resume: (refreshed) => guard.resumeWith(refreshed)
|
|
21541
|
+
});
|
|
21542
|
+
let value;
|
|
21543
|
+
try {
|
|
21544
|
+
value = await registration.handler(ctx);
|
|
21545
|
+
} catch (error) {
|
|
21546
|
+
await guard.stop();
|
|
21547
|
+
if (ctx.hasUncertainMutation) throw asError(error, "durable workflow mutation result is uncertain");
|
|
21548
|
+
await applyHandlerError(workflow, workerOptions, ctx, registration, error);
|
|
21549
|
+
return;
|
|
21550
|
+
}
|
|
21551
|
+
await guard.stop();
|
|
21552
|
+
if (ctx.hasUncertainMutation) {
|
|
21553
|
+
throw asError(ctx.uncertainMutationFailure, "durable workflow mutation result is uncertain");
|
|
21554
|
+
}
|
|
21555
|
+
if (isAlreadyAppliedOutcome(value)) {
|
|
21556
|
+
ctx.assertAppliedOutcome(value);
|
|
21557
|
+
await releaseAppliedMutation(workflow, ctx);
|
|
21558
|
+
return;
|
|
21559
|
+
}
|
|
21560
|
+
if (isReplayedStepResult(value)) {
|
|
21561
|
+
await applyWorkflowOutcome(
|
|
21562
|
+
workflow.client,
|
|
21563
|
+
ctx,
|
|
21564
|
+
complete({ result: value.result }),
|
|
21565
|
+
registration.returnRecord
|
|
21566
|
+
);
|
|
21567
|
+
return;
|
|
21568
|
+
}
|
|
21569
|
+
if (isOutcome(value)) {
|
|
21570
|
+
await applyWorkflowOutcome(workflow.client, ctx, value, registration.returnRecord);
|
|
21571
|
+
return;
|
|
21572
|
+
}
|
|
21573
|
+
if (ctx.hasAppliedMutation) {
|
|
21574
|
+
await releaseAppliedMutation(workflow, ctx);
|
|
21575
|
+
return;
|
|
21576
|
+
}
|
|
21577
|
+
await applyWorkflowOutcome(
|
|
21578
|
+
workflow.client,
|
|
21579
|
+
ctx,
|
|
21580
|
+
complete({ result: value }),
|
|
21581
|
+
registration.returnRecord
|
|
21582
|
+
);
|
|
21583
|
+
}
|
|
21584
|
+
function asError(value, message) {
|
|
21585
|
+
return value instanceof Error ? value : new Error(message, { cause: value });
|
|
21586
|
+
}
|
|
21587
|
+
async function releaseAppliedMutation(workflow, ctx) {
|
|
21588
|
+
await workflow.client.transition(ctx.id, {
|
|
21589
|
+
fencingToken: ctx.fencingToken,
|
|
21590
|
+
fromState: ctx.state,
|
|
21591
|
+
leaseToken: ctx.leaseToken,
|
|
21592
|
+
partitionKey: ctx.partitionKey,
|
|
21593
|
+
toState: ctx.logicalState
|
|
20980
21594
|
});
|
|
20981
21595
|
}
|
|
21596
|
+
async function applyHandlerError(workflow, workerOptions, ctx, registration, error) {
|
|
21597
|
+
const policy = workerOptions.exceptionPolicy ?? registration.exceptionPolicy;
|
|
21598
|
+
if (policy === "raise") throw error;
|
|
21599
|
+
const encodedError = workerErrorPayload(error, workerOptions, workflow.client.codec);
|
|
21600
|
+
await applyWorkflowOutcome(
|
|
21601
|
+
workflow.client,
|
|
21602
|
+
ctx,
|
|
21603
|
+
policy === "fail" ? fail2({ error: encodedError }) : retry({ error: encodedError }),
|
|
21604
|
+
registration.returnRecord
|
|
21605
|
+
);
|
|
21606
|
+
}
|
|
20982
21607
|
|
|
20983
21608
|
// src/workflow.ts
|
|
20984
21609
|
var WorkflowClient = class {
|
|
@@ -21107,6 +21732,10 @@ var WorkflowWorker = class {
|
|
|
21107
21732
|
claimed += jobs.length;
|
|
21108
21733
|
const guards = jobs.map((job) => new LeaseRenewalGuard(this.workflow.client, job, leaseMs, this.options));
|
|
21109
21734
|
let cursor = 0;
|
|
21735
|
+
let batchFailure;
|
|
21736
|
+
const recordFailure = (error) => {
|
|
21737
|
+
batchFailure ??= { error };
|
|
21738
|
+
};
|
|
21110
21739
|
const runNext = async () => {
|
|
21111
21740
|
while (cursor < jobs.length) {
|
|
21112
21741
|
const index = cursor;
|
|
@@ -21117,19 +21746,22 @@ var WorkflowWorker = class {
|
|
|
21117
21746
|
try {
|
|
21118
21747
|
await this.applyJob(job, registration, guard);
|
|
21119
21748
|
applied += 1;
|
|
21749
|
+
} catch (error) {
|
|
21750
|
+
recordFailure(error);
|
|
21120
21751
|
} finally {
|
|
21121
|
-
|
|
21752
|
+
try {
|
|
21753
|
+
await guard.stop();
|
|
21754
|
+
} catch (error) {
|
|
21755
|
+
recordFailure(error);
|
|
21756
|
+
}
|
|
21122
21757
|
}
|
|
21123
21758
|
}
|
|
21124
21759
|
};
|
|
21125
21760
|
try {
|
|
21126
|
-
|
|
21761
|
+
await Promise.all(
|
|
21127
21762
|
Array.from({ length: Math.min(concurrency, jobs.length) }, () => runNext())
|
|
21128
21763
|
);
|
|
21129
|
-
|
|
21130
|
-
if (failed != null) {
|
|
21131
|
-
throw failed.reason;
|
|
21132
|
-
}
|
|
21764
|
+
if (batchFailure != null) throwError(batchFailure.error);
|
|
21133
21765
|
} finally {
|
|
21134
21766
|
await Promise.allSettled(
|
|
21135
21767
|
guards.slice(cursor).map(async (guard) => await guard.stop())
|
|
@@ -21240,45 +21872,15 @@ var WorkflowWorker = class {
|
|
|
21240
21872
|
});
|
|
21241
21873
|
}
|
|
21242
21874
|
async applyJob(job, registration, guard) {
|
|
21243
|
-
guard
|
|
21244
|
-
const ctx = new WorkflowContext(this.workflow, job, registration.name, guard.job);
|
|
21245
|
-
let outcome;
|
|
21246
|
-
try {
|
|
21247
|
-
const value = await registration.handler(ctx);
|
|
21248
|
-
outcome = isOutcome(value) ? value : complete({ result: value });
|
|
21249
|
-
} catch (error) {
|
|
21250
|
-
await guard.stop();
|
|
21251
|
-
await this.applyHandlerError(ctx, registration, error);
|
|
21252
|
-
return;
|
|
21253
|
-
}
|
|
21254
|
-
await guard.stop();
|
|
21255
|
-
await applyWorkflowOutcome(this.workflow.client, ctx, outcome, registration.returnRecord);
|
|
21256
|
-
}
|
|
21257
|
-
async applyHandlerError(ctx, registration, error) {
|
|
21258
|
-
const policy = this.options.exceptionPolicy ?? registration.exceptionPolicy;
|
|
21259
|
-
if (policy === "raise") {
|
|
21260
|
-
throw error;
|
|
21261
|
-
}
|
|
21262
|
-
if (policy === "fail") {
|
|
21263
|
-
await applyWorkflowOutcome(
|
|
21264
|
-
this.workflow.client,
|
|
21265
|
-
ctx,
|
|
21266
|
-
fail2({ error: workerErrorPayload(error, this.options, this.workflow.client.codec) }),
|
|
21267
|
-
registration.returnRecord
|
|
21268
|
-
);
|
|
21269
|
-
return;
|
|
21270
|
-
}
|
|
21271
|
-
await applyWorkflowOutcome(
|
|
21272
|
-
this.workflow.client,
|
|
21273
|
-
ctx,
|
|
21274
|
-
retry({ error: workerErrorPayload(error, this.options, this.workflow.client.codec) }),
|
|
21275
|
-
registration.returnRecord
|
|
21276
|
-
);
|
|
21875
|
+
await executeWorkflowJob(this.workflow, this.options, job, registration, guard);
|
|
21277
21876
|
}
|
|
21278
21877
|
};
|
|
21878
|
+
function throwError(value) {
|
|
21879
|
+
throw value instanceof Error ? value : new Error("workflow worker failed", { cause: value });
|
|
21880
|
+
}
|
|
21279
21881
|
|
|
21280
21882
|
// src/version.ts
|
|
21281
|
-
var FERRICSTORE_SDK_VERSION = "0.
|
|
21883
|
+
var FERRICSTORE_SDK_VERSION = "0.13.1";
|
|
21282
21884
|
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.4";
|
|
21283
21885
|
var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
|
|
21284
21886
|
export {
|
|
@@ -21321,6 +21923,7 @@ export {
|
|
|
21321
21923
|
QueueWorker,
|
|
21322
21924
|
RawCodec,
|
|
21323
21925
|
ReconnectingExecutor,
|
|
21926
|
+
RequestNotSentError,
|
|
21324
21927
|
RequestTimeoutError,
|
|
21325
21928
|
RerouteError,
|
|
21326
21929
|
RoutingTopology,
|
|
@@ -21341,6 +21944,7 @@ export {
|
|
|
21341
21944
|
complete,
|
|
21342
21945
|
fail2 as fail,
|
|
21343
21946
|
httpCommandDisposition,
|
|
21947
|
+
isAlreadyAppliedOutcome,
|
|
21344
21948
|
isOutcome,
|
|
21345
21949
|
isReconnectableClosedConnectionError,
|
|
21346
21950
|
mapException,
|