@workflow/world-testing 5.0.0-beta.54 → 5.0.0-beta.56
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.
|
@@ -21110,7 +21110,30 @@ var init_events2 = __esm({
|
|
|
21110
21110
|
tokenRetentionUntil: external_exports2.coerce.date().optional(),
|
|
21111
21111
|
metadata: SerializedDataSchema2.optional(),
|
|
21112
21112
|
isWebhook: external_exports2.boolean().optional(),
|
|
21113
|
-
isSystem: external_exports2.boolean().optional()
|
|
21113
|
+
isSystem: external_exports2.boolean().optional(),
|
|
21114
|
+
/**
|
|
21115
|
+
* `createHook({ experimental_force: true })`: when the token belongs to
|
|
21116
|
+
* another live run, the World takes it over — journaling
|
|
21117
|
+
* `hook_disposed{forceClaimedBy}` in that run's log and re-pointing the
|
|
21118
|
+
* token — instead of answering `hook_conflict`. Requires the
|
|
21119
|
+
* `hookForceClaim` capability.
|
|
21120
|
+
*/
|
|
21121
|
+
force: external_exports2.boolean().optional(),
|
|
21122
|
+
/**
|
|
21123
|
+
* World-written on a forced creation that did take a token over: the
|
|
21124
|
+
* run and hook it was taken from, plus what a queue message to that run
|
|
21125
|
+
* needs (`workflowName`, `deploymentId`, `runSpecVersion`). Absent when
|
|
21126
|
+
* the token was free. The wake-targeting fields are in the LOG, not only
|
|
21127
|
+
* on the hook entity, so a replay can republish the victim's wake from
|
|
21128
|
+
* the row alone; see `publishForceClaimVictimWake` in @workflow/core.
|
|
21129
|
+
*/
|
|
21130
|
+
forceClaimedFrom: external_exports2.object({
|
|
21131
|
+
runId: external_exports2.string(),
|
|
21132
|
+
hookId: external_exports2.string(),
|
|
21133
|
+
workflowName: external_exports2.string().optional(),
|
|
21134
|
+
deploymentId: external_exports2.string().optional(),
|
|
21135
|
+
runSpecVersion: external_exports2.number().optional()
|
|
21136
|
+
}).optional()
|
|
21114
21137
|
})
|
|
21115
21138
|
}));
|
|
21116
21139
|
HookReceivedEventSchema2 = external_exports2.compile(BaseEventSchema2.extend({
|
|
@@ -21125,7 +21148,14 @@ var init_events2 = __esm({
|
|
|
21125
21148
|
eventType: external_exports2.literal("hook_disposed"),
|
|
21126
21149
|
correlationId: external_exports2.string(),
|
|
21127
21150
|
eventData: external_exports2.object({
|
|
21128
|
-
token: external_exports2.string().optional()
|
|
21151
|
+
token: external_exports2.string().optional(),
|
|
21152
|
+
/**
|
|
21153
|
+
* World-written: this disposal was not the run's own. Another run
|
|
21154
|
+
* took the hook's token with `experimental_force`, and this names
|
|
21155
|
+
* it. The hook consumer rejects the hook's awaiters with
|
|
21156
|
+
* `HookForceClaimedError` when it reads this row.
|
|
21157
|
+
*/
|
|
21158
|
+
forceClaimedBy: external_exports2.object({ runId: external_exports2.string(), hookId: external_exports2.string() }).optional()
|
|
21129
21159
|
}).optional()
|
|
21130
21160
|
}));
|
|
21131
21161
|
HookConflictEventSchema2 = external_exports2.compile(BaseEventSchema2.extend({
|
|
@@ -21135,7 +21165,18 @@ var init_events2 = __esm({
|
|
|
21135
21165
|
token: external_exports2.string(),
|
|
21136
21166
|
// TODO: Make this required once all persisted hook_conflict events and
|
|
21137
21167
|
// remote World implementations always include the active hook owner's run ID.
|
|
21138
|
-
conflictingRunId: external_exports2.string().optional()
|
|
21168
|
+
conflictingRunId: external_exports2.string().optional(),
|
|
21169
|
+
/**
|
|
21170
|
+
* Set when the creation asked for `force` and the World declined to take
|
|
21171
|
+
* the token over. `victim-spec-version`: the run holding the token was
|
|
21172
|
+
* started at a spec version below
|
|
21173
|
+
* `SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM`, so its runtime would not
|
|
21174
|
+
* understand the involuntary disposal — the forced hook gets the
|
|
21175
|
+
* ordinary `HookConflictError` it opted out of instead of stranding
|
|
21176
|
+
* that run. Absent on a conflict answered by a World that does not
|
|
21177
|
+
* implement forcing at all.
|
|
21178
|
+
*/
|
|
21179
|
+
forceRefusedReason: external_exports2.literal("victim-spec-version").optional()
|
|
21139
21180
|
})
|
|
21140
21181
|
}));
|
|
21141
21182
|
NoopEventSchema2 = external_exports2.compile(BaseEventSchema2.extend({
|
|
@@ -22035,7 +22076,7 @@ var init_queue2 = __esm({
|
|
|
22035
22076
|
});
|
|
22036
22077
|
|
|
22037
22078
|
// ../world/dist/hooks.js
|
|
22038
|
-
var HookResumeContextSchema2, HOOK_RESUME_INPUT_VERSION2, HOOK_RESUME_DEDUP_VERSION2, HookResumeCapabilitiesSchema2, HookSchema2;
|
|
22079
|
+
var HookResumeContextSchema2, HOOK_RESUME_INPUT_VERSION2, HOOK_RESUME_DEDUP_VERSION2, HookResumeCapabilitiesSchema2, HookClaimedFromSchema2, HookSchema2;
|
|
22039
22080
|
var init_hooks2 = __esm({
|
|
22040
22081
|
"../world/dist/hooks.js"() {
|
|
22041
22082
|
"use strict";
|
|
@@ -22076,6 +22117,13 @@ var init_hooks2 = __esm({
|
|
|
22076
22117
|
// is engaged.
|
|
22077
22118
|
hookResumeDedupVersion: external_exports2.number()
|
|
22078
22119
|
}));
|
|
22120
|
+
HookClaimedFromSchema2 = external_exports2.compile(external_exports2.object({
|
|
22121
|
+
runId: external_exports2.string(),
|
|
22122
|
+
hookId: external_exports2.string(),
|
|
22123
|
+
workflowName: external_exports2.string().optional(),
|
|
22124
|
+
deploymentId: external_exports2.string().optional(),
|
|
22125
|
+
runSpecVersion: external_exports2.number().optional()
|
|
22126
|
+
}));
|
|
22079
22127
|
HookSchema2 = external_exports2.compile(external_exports2.object({
|
|
22080
22128
|
runId: external_exports2.string(),
|
|
22081
22129
|
hookId: external_exports2.string(),
|
|
@@ -22103,7 +22151,12 @@ var init_hooks2 = __esm({
|
|
|
22103
22151
|
// `resumeHook()` gates its lazy path on this being present and
|
|
22104
22152
|
// current. Absent against an older/rolled-back server or when the kill switch
|
|
22105
22153
|
// is active.
|
|
22106
|
-
resumeCapabilities: HookResumeCapabilitiesSchema2.optional()
|
|
22154
|
+
resumeCapabilities: HookResumeCapabilitiesSchema2.optional(),
|
|
22155
|
+
// Set when this hook took its token from another run
|
|
22156
|
+
// (`experimental_force`). The wake-targeting fields are the victim run's,
|
|
22157
|
+
// so the claimer's runtime can publish the victim's wake without reading
|
|
22158
|
+
// a run it may not be able to reach; see `HookClaimedFromSchema`.
|
|
22159
|
+
claimedFrom: HookClaimedFromSchema2.optional()
|
|
22107
22160
|
}));
|
|
22108
22161
|
}
|
|
22109
22162
|
});
|
|
@@ -22276,7 +22329,7 @@ function requiresNewerWorld(v) {
|
|
|
22276
22329
|
return false;
|
|
22277
22330
|
return v > SPEC_VERSION_MAX_SUPPORTED2;
|
|
22278
22331
|
}
|
|
22279
|
-
var SPEC_VERSION_LEGACY2, SPEC_VERSION_SUPPORTS_EVENT_SOURCING, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT2, SPEC_VERSION_SUPPORTS_ATTRIBUTES2, SPEC_VERSION_SUPPORTS_COMPRESSION2, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY2,
|
|
22332
|
+
var SPEC_VERSION_LEGACY2, SPEC_VERSION_SUPPORTS_EVENT_SOURCING, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT2, SPEC_VERSION_SUPPORTS_ATTRIBUTES2, SPEC_VERSION_SUPPORTS_COMPRESSION2, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY2, SPEC_VERSION_SUPPORTS_SEALED_LOG, SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM2, SPEC_VERSION_CURRENT2, SEALED_LOG_ENV_VAR, SPEC_VERSION_MAX_SUPPORTED2;
|
|
22280
22333
|
var init_spec_version2 = __esm({
|
|
22281
22334
|
"../world/dist/spec-version.js"() {
|
|
22282
22335
|
"use strict";
|
|
@@ -22287,11 +22340,12 @@ var init_spec_version2 = __esm({
|
|
|
22287
22340
|
SPEC_VERSION_SUPPORTS_ATTRIBUTES2 = 4;
|
|
22288
22341
|
SPEC_VERSION_SUPPORTS_COMPRESSION2 = 5;
|
|
22289
22342
|
SPEC_VERSION_SUPPORTS_SLOT_IDENTITY2 = 6;
|
|
22290
|
-
|
|
22291
|
-
|
|
22343
|
+
SPEC_VERSION_SUPPORTS_SEALED_LOG = 7;
|
|
22344
|
+
SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM2 = 8;
|
|
22345
|
+
SPEC_VERSION_CURRENT2 = SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM2;
|
|
22292
22346
|
SEALED_LOG_ENV_VAR = "WORKFLOW_SEALED_LOG";
|
|
22293
22347
|
__name(mintedSpecVersion, "mintedSpecVersion");
|
|
22294
|
-
SPEC_VERSION_MAX_SUPPORTED2 =
|
|
22348
|
+
SPEC_VERSION_MAX_SUPPORTED2 = SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM2;
|
|
22295
22349
|
__name(isLegacySpecVersion2, "isLegacySpecVersion");
|
|
22296
22350
|
__name(requiresNewerWorld, "requiresNewerWorld");
|
|
22297
22351
|
}
|
|
@@ -22557,6 +22611,7 @@ __export(dist_exports, {
|
|
|
22557
22611
|
HOOK_RESUME_DEDUP_VERSION: () => HOOK_RESUME_DEDUP_VERSION2,
|
|
22558
22612
|
HOOK_RESUME_INPUT_VERSION: () => HOOK_RESUME_INPUT_VERSION2,
|
|
22559
22613
|
HealthCheckPayloadSchema: () => HealthCheckPayloadSchema2,
|
|
22614
|
+
HookClaimedFromSchema: () => HookClaimedFromSchema2,
|
|
22560
22615
|
HookCreatedEventSchema: () => HookCreatedEventSchema2,
|
|
22561
22616
|
HookResumeCapabilitiesSchema: () => HookResumeCapabilitiesSchema2,
|
|
22562
22617
|
HookSchema: () => HookSchema2,
|
|
@@ -22585,7 +22640,8 @@ __export(dist_exports, {
|
|
|
22585
22640
|
SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT: () => SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT2,
|
|
22586
22641
|
SPEC_VERSION_SUPPORTS_COMPRESSION: () => SPEC_VERSION_SUPPORTS_COMPRESSION2,
|
|
22587
22642
|
SPEC_VERSION_SUPPORTS_EVENT_SOURCING: () => SPEC_VERSION_SUPPORTS_EVENT_SOURCING,
|
|
22588
|
-
|
|
22643
|
+
SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM: () => SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM2,
|
|
22644
|
+
SPEC_VERSION_SUPPORTS_SEALED_LOG: () => SPEC_VERSION_SUPPORTS_SEALED_LOG,
|
|
22589
22645
|
SPEC_VERSION_SUPPORTS_SLOT_IDENTITY: () => SPEC_VERSION_SUPPORTS_SLOT_IDENTITY2,
|
|
22590
22646
|
STEP_EVENT_TYPES: () => STEP_EVENT_TYPES2,
|
|
22591
22647
|
SerializedDataSchema: () => SerializedDataSchema2,
|
|
@@ -22730,7 +22786,7 @@ function buildFramedDetails2(hint3, slug) {
|
|
|
22730
22786
|
out.push({ label: "docs", value: `${BASE_URL2}/${slug}` });
|
|
22731
22787
|
return out;
|
|
22732
22788
|
}
|
|
22733
|
-
var BASE_URL2, ERROR_SLUGS2, WorkflowError2, WorkflowWorldError2, WorkflowRunFailedError2, WorkflowRunNotCompletedError2, WorkflowRuntimeError2, CorruptedEventLogError, ReplayDivergenceError, MaxEventsExceededError, RuntimeDecryptionError2, SerializationError2, StepNotRegisteredError2, WorkflowNotRegisteredError2, WorkflowDeploymentMismatchError, WorkflowRunNotFoundError2, HookConflictError2, HookNotFoundError2, EntityConflictError2, RunExpiredError2, StreamError2, StreamExpiredError2, TooEarlyError, ThrottleError2, PreconditionFailedError, WorkflowRunCancelledError2, RunNotSupportedError, FatalError2, RetryableError2, FATAL_ERROR_KEY2, RETRYABLE_ERROR_KEY2, HOOK_CONFLICT_ERROR_KEY2, RUNTIME_DECRYPTION_ERROR_KEY2, STREAM_ERROR_KEY2;
|
|
22789
|
+
var BASE_URL2, ERROR_SLUGS2, WorkflowError2, WorkflowWorldError2, WorkflowRunFailedError2, WorkflowRunNotCompletedError2, WorkflowRuntimeError2, CorruptedEventLogError, ReplayDivergenceError, MaxEventsExceededError, RuntimeDecryptionError2, SerializationError2, StepNotRegisteredError2, WorkflowNotRegisteredError2, WorkflowDeploymentMismatchError, WorkflowRunNotFoundError2, HookConflictError2, HookForceClaimedError2, HookNotFoundError2, EntityConflictError2, RunExpiredError2, StreamError2, StreamExpiredError2, TooEarlyError, ThrottleError2, PreconditionFailedError, WorkflowRunCancelledError2, RunNotSupportedError, FatalError2, RetryableError2, FATAL_ERROR_KEY2, RETRYABLE_ERROR_KEY2, HOOK_CONFLICT_ERROR_KEY2, HOOK_FORCE_CLAIMED_ERROR_KEY2, RUNTIME_DECRYPTION_ERROR_KEY2, STREAM_ERROR_KEY2;
|
|
22734
22790
|
var init_dist7 = __esm({
|
|
22735
22791
|
"../errors/dist/index.js"() {
|
|
22736
22792
|
"use strict";
|
|
@@ -22750,6 +22806,7 @@ var init_dist7 = __esm({
|
|
|
22750
22806
|
FETCH_IN_WORKFLOW_FUNCTION: "fetch-in-workflow",
|
|
22751
22807
|
TIMEOUT_FUNCTIONS_IN_WORKFLOW: "timeout-in-workflow",
|
|
22752
22808
|
HOOK_CONFLICT: "hook-conflict",
|
|
22809
|
+
HOOK_FORCE_CLAIMED: "hook-force-claimed",
|
|
22753
22810
|
CORRUPTED_EVENT_LOG: "corrupted-event-log",
|
|
22754
22811
|
REPLAY_DIVERGENCE: "replay-divergence",
|
|
22755
22812
|
STEP_NOT_REGISTERED: "step-not-registered",
|
|
@@ -23043,6 +23100,28 @@ Caused by: ${options.cause.stack}`;
|
|
|
23043
23100
|
return isError2(value) && value.name === "HookConflictError";
|
|
23044
23101
|
}
|
|
23045
23102
|
};
|
|
23103
|
+
HookForceClaimedError2 = class extends WorkflowError2 {
|
|
23104
|
+
static {
|
|
23105
|
+
__name(this, "HookForceClaimedError");
|
|
23106
|
+
}
|
|
23107
|
+
token;
|
|
23108
|
+
/** The run that took the token. */
|
|
23109
|
+
claimedByRunId;
|
|
23110
|
+
/** The hook (in `claimedByRunId`) the token now belongs to. */
|
|
23111
|
+
claimedByHookId;
|
|
23112
|
+
constructor(token, claimedByRunId, claimedByHookId) {
|
|
23113
|
+
super(`Hook token "${token}" was force-claimed by another workflow (run "${claimedByRunId}")`, { slug: ERROR_SLUGS2.HOOK_FORCE_CLAIMED });
|
|
23114
|
+
this.name = "HookForceClaimedError";
|
|
23115
|
+
this.token = token;
|
|
23116
|
+
this.claimedByRunId = claimedByRunId;
|
|
23117
|
+
if (claimedByHookId !== void 0) {
|
|
23118
|
+
this.claimedByHookId = claimedByHookId;
|
|
23119
|
+
}
|
|
23120
|
+
}
|
|
23121
|
+
static is(value) {
|
|
23122
|
+
return isError2(value) && value.name === "HookForceClaimedError";
|
|
23123
|
+
}
|
|
23124
|
+
};
|
|
23046
23125
|
HookNotFoundError2 = class extends WorkflowError2 {
|
|
23047
23126
|
static {
|
|
23048
23127
|
__name(this, "HookNotFoundError");
|
|
@@ -23233,6 +23312,7 @@ Caused by: ${options.cause.stack}`;
|
|
|
23233
23312
|
FATAL_ERROR_KEY2 = /* @__PURE__ */ Symbol.for("@workflow/errors//FatalError");
|
|
23234
23313
|
RETRYABLE_ERROR_KEY2 = /* @__PURE__ */ Symbol.for("@workflow/errors//RetryableError");
|
|
23235
23314
|
HOOK_CONFLICT_ERROR_KEY2 = /* @__PURE__ */ Symbol.for("@workflow/errors//HookConflictError");
|
|
23315
|
+
HOOK_FORCE_CLAIMED_ERROR_KEY2 = /* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError");
|
|
23236
23316
|
RUNTIME_DECRYPTION_ERROR_KEY2 = /* @__PURE__ */ Symbol.for("@workflow/errors//RuntimeDecryptionError");
|
|
23237
23317
|
STREAM_ERROR_KEY2 = /* @__PURE__ */ Symbol.for("@workflow/errors//StreamError");
|
|
23238
23318
|
if (typeof globalThis !== "undefined") {
|
|
@@ -23260,6 +23340,14 @@ Caused by: ${options.cause.stack}`;
|
|
|
23260
23340
|
configurable: false
|
|
23261
23341
|
});
|
|
23262
23342
|
}
|
|
23343
|
+
if (!Object.hasOwn(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY2)) {
|
|
23344
|
+
Object.defineProperty(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY2, {
|
|
23345
|
+
value: HookForceClaimedError2,
|
|
23346
|
+
writable: false,
|
|
23347
|
+
enumerable: false,
|
|
23348
|
+
configurable: false
|
|
23349
|
+
});
|
|
23350
|
+
}
|
|
23263
23351
|
if (!Object.hasOwn(globalThis, RUNTIME_DECRYPTION_ERROR_KEY2)) {
|
|
23264
23352
|
Object.defineProperty(globalThis, RUNTIME_DECRYPTION_ERROR_KEY2, {
|
|
23265
23353
|
value: RuntimeDecryptionError2,
|
|
@@ -54921,6 +55009,35 @@ function hookDisposeLockPath(basedir, hookId, tag) {
|
|
|
54921
55009
|
const name = tag ? `${hookId}.disposed.${tag}` : `${hookId}.disposed`;
|
|
54922
55010
|
return resolveWithinBase(basedir, ".locks", "hooks", name);
|
|
54923
55011
|
}
|
|
55012
|
+
async function readHookDisposeLock(basedir, hookId, tag) {
|
|
55013
|
+
const candidates = [hookDisposeLockPath(basedir, hookId)];
|
|
55014
|
+
if (tag) {
|
|
55015
|
+
candidates.push(hookDisposeLockPath(basedir, hookId, tag));
|
|
55016
|
+
}
|
|
55017
|
+
for (const lockPath of candidates) {
|
|
55018
|
+
let content;
|
|
55019
|
+
try {
|
|
55020
|
+
content = await fs2.readFile(lockPath, "utf8");
|
|
55021
|
+
} catch {
|
|
55022
|
+
continue;
|
|
55023
|
+
}
|
|
55024
|
+
if (content.trim() === "")
|
|
55025
|
+
return { committed: true };
|
|
55026
|
+
try {
|
|
55027
|
+
const parsed = JSON.parse(content);
|
|
55028
|
+
const by = parsed.forceClaimedBy;
|
|
55029
|
+
if (by && typeof by.runId === "string" && typeof by.hookId === "string") {
|
|
55030
|
+
return {
|
|
55031
|
+
committed: true,
|
|
55032
|
+
forceClaimedBy: { runId: by.runId, hookId: by.hookId }
|
|
55033
|
+
};
|
|
55034
|
+
}
|
|
55035
|
+
} catch {
|
|
55036
|
+
}
|
|
55037
|
+
return { committed: true };
|
|
55038
|
+
}
|
|
55039
|
+
return { committed: false };
|
|
55040
|
+
}
|
|
54924
55041
|
async function isHookDisposalCommitted(basedir, hookId, tag) {
|
|
54925
55042
|
const candidates = [hookDisposeLockPath(basedir, hookId)];
|
|
54926
55043
|
if (tag) {
|
|
@@ -55136,6 +55253,7 @@ var init_helpers2 = __esm({
|
|
|
55136
55253
|
init_fs();
|
|
55137
55254
|
__name(hashToken, "hashToken");
|
|
55138
55255
|
__name(hookDisposeLockPath, "hookDisposeLockPath");
|
|
55256
|
+
__name(readHookDisposeLock, "readHookDisposeLock");
|
|
55139
55257
|
__name(isHookDisposalCommitted, "isHookDisposalCommitted");
|
|
55140
55258
|
__name(runTerminalMarkerPath, "runTerminalMarkerPath");
|
|
55141
55259
|
__name(isRunTerminalCommitted, "isRunTerminalCommitted");
|
|
@@ -55153,7 +55271,17 @@ var init_helpers2 = __esm({
|
|
|
55153
55271
|
// Legacy claims also omitted eventId. Their recovery marker pins the
|
|
55154
55272
|
// canonical hook_created event before concurrent retries publish it.
|
|
55155
55273
|
eventId: external_exports2.string().optional(),
|
|
55156
|
-
tokenRetentionUntil: external_exports2.coerce.date().optional()
|
|
55274
|
+
tokenRetentionUntil: external_exports2.coerce.date().optional(),
|
|
55275
|
+
// Set when this claim took the token from another run
|
|
55276
|
+
// (`experimental_force`), so a retry that adopts the claim can still
|
|
55277
|
+
// report — and wake — the run it came from.
|
|
55278
|
+
claimedFrom: external_exports2.object({
|
|
55279
|
+
runId: external_exports2.string(),
|
|
55280
|
+
hookId: external_exports2.string(),
|
|
55281
|
+
workflowName: external_exports2.string().optional(),
|
|
55282
|
+
deploymentId: external_exports2.string().optional(),
|
|
55283
|
+
runSpecVersion: external_exports2.number().optional()
|
|
55284
|
+
}).optional()
|
|
55157
55285
|
}));
|
|
55158
55286
|
__name(readHookTokenClaim, "readHookTokenClaim");
|
|
55159
55287
|
__name(withHookTokenClaimLock, "withHookTokenClaimLock");
|
|
@@ -55217,7 +55345,7 @@ async function writeHookCreatedIndexEntries(basedir, token, runId, hookId, event
|
|
|
55217
55345
|
assertSafeEntityId("eventId", eventId);
|
|
55218
55346
|
if (tag !== void 0)
|
|
55219
55347
|
assertSafeEntityId("tag", tag);
|
|
55220
|
-
const fileName = tag ? `${eventId}.${tag}.json` : `${eventId}.json`;
|
|
55348
|
+
const fileName = tag ? `${runId}-${eventId}.${tag}.json` : `${runId}-${eventId}.json`;
|
|
55221
55349
|
const content = JSON.stringify({ runId });
|
|
55222
55350
|
await Promise.all([
|
|
55223
55351
|
writeExclusive(path5.join(tokenIndexDir(basedir, token), fileName), content),
|
|
@@ -55324,7 +55452,7 @@ async function ensureHookIndexesImpl(basedir) {
|
|
|
55324
55452
|
});
|
|
55325
55453
|
await writeExclusive(markerPath, "");
|
|
55326
55454
|
}
|
|
55327
|
-
async function
|
|
55455
|
+
async function findIndexedHookCreatedEvent(basedir, index, accept, tag) {
|
|
55328
55456
|
await ensureHookIndexes(basedir);
|
|
55329
55457
|
let dir;
|
|
55330
55458
|
try {
|
|
@@ -55332,6 +55460,10 @@ async function findNewestIndexedHookCreatedEvent(basedir, index, matches, tag) {
|
|
|
55332
55460
|
} catch {
|
|
55333
55461
|
return null;
|
|
55334
55462
|
}
|
|
55463
|
+
const eventIdOf = /* @__PURE__ */ __name((entryId, runId) => {
|
|
55464
|
+
const stripped = stripTag(entryId);
|
|
55465
|
+
return stripped.startsWith(`${runId}-`) ? stripped.slice(runId.length + 1) : stripped;
|
|
55466
|
+
}, "eventIdOf");
|
|
55335
55467
|
const entryIds = (await listJSONFiles(dir)).filter((fileId) => isVisibleToTag(fileId, tag)).sort((a, b) => stripTag(b).localeCompare(stripTag(a)));
|
|
55336
55468
|
for (const entryId of entryIds) {
|
|
55337
55469
|
let entry = null;
|
|
@@ -55344,7 +55476,7 @@ async function findNewestIndexedHookCreatedEvent(basedir, index, matches, tag) {
|
|
|
55344
55476
|
}
|
|
55345
55477
|
if (!entry)
|
|
55346
55478
|
continue;
|
|
55347
|
-
const eventId =
|
|
55479
|
+
const eventId = eventIdOf(entryId, entry.runId);
|
|
55348
55480
|
let eventPath;
|
|
55349
55481
|
try {
|
|
55350
55482
|
eventPath = taggedPath(basedir, "events", `${entry.runId}-${eventId}`, tagOf(entryId));
|
|
@@ -55358,7 +55490,7 @@ async function findNewestIndexedHookCreatedEvent(basedir, index, matches, tag) {
|
|
|
55358
55490
|
continue;
|
|
55359
55491
|
if (typeof event.correlationId !== "string")
|
|
55360
55492
|
continue;
|
|
55361
|
-
if (!
|
|
55493
|
+
if (!await accept(event))
|
|
55362
55494
|
continue;
|
|
55363
55495
|
return event;
|
|
55364
55496
|
}
|
|
@@ -55398,7 +55530,7 @@ var init_hook_index = __esm({
|
|
|
55398
55530
|
__name(ensureHookIndexes, "ensureHookIndexes");
|
|
55399
55531
|
__name(forEachConcurrent, "forEachConcurrent");
|
|
55400
55532
|
__name(ensureHookIndexesImpl, "ensureHookIndexesImpl");
|
|
55401
|
-
__name(
|
|
55533
|
+
__name(findIndexedHookCreatedEvent, "findIndexedHookCreatedEvent");
|
|
55402
55534
|
}
|
|
55403
55535
|
});
|
|
55404
55536
|
|
|
@@ -55449,11 +55581,14 @@ function getHookCreatedToken(event) {
|
|
|
55449
55581
|
return typeof token === "string" ? token : void 0;
|
|
55450
55582
|
}
|
|
55451
55583
|
function hookFromCreatedEvent(event) {
|
|
55452
|
-
const { token, metadata, isWebhook, isSystem, tokenRetentionUntil } = event.eventData;
|
|
55584
|
+
const { token, metadata, isWebhook, isSystem, tokenRetentionUntil, forceClaimedFrom } = event.eventData;
|
|
55453
55585
|
return {
|
|
55454
55586
|
runId: event.runId,
|
|
55455
55587
|
hookId: event.correlationId,
|
|
55456
55588
|
token,
|
|
55589
|
+
// The journaled row is the durable record of a takeover; a rebuilt
|
|
55590
|
+
// entity must say where its token came from just as the original did.
|
|
55591
|
+
...forceClaimedFrom !== void 0 && { claimedFrom: forceClaimedFrom },
|
|
55457
55592
|
metadata,
|
|
55458
55593
|
ownerId: "local-owner",
|
|
55459
55594
|
projectId: "local-project",
|
|
@@ -55473,20 +55608,17 @@ async function isTerminalRunCache(basedir, runId, tag) {
|
|
|
55473
55608
|
return run3 ? isTerminalWorkflowRunStatus2(run3.status) : false;
|
|
55474
55609
|
}
|
|
55475
55610
|
async function findAvailableHookCreatedEvent(basedir, index, matches, tag) {
|
|
55476
|
-
const
|
|
55477
|
-
|
|
55478
|
-
|
|
55479
|
-
|
|
55480
|
-
|
|
55481
|
-
|
|
55482
|
-
if (!retainedUntil || retainedUntil.getTime() <= Date.now()) {
|
|
55483
|
-
return null;
|
|
55611
|
+
const isLive = /* @__PURE__ */ __name(async (event) => {
|
|
55612
|
+
if (await isTerminalRunCache(basedir, event.runId, tag)) {
|
|
55613
|
+
const retainedUntil = event.eventData.tokenRetentionUntil;
|
|
55614
|
+
if (!retainedUntil || retainedUntil.getTime() <= Date.now()) {
|
|
55615
|
+
return false;
|
|
55616
|
+
}
|
|
55484
55617
|
}
|
|
55485
|
-
|
|
55486
|
-
|
|
55487
|
-
|
|
55488
|
-
|
|
55489
|
-
return newest;
|
|
55618
|
+
return !await isHookDisposalCommitted(basedir, event.correlationId, tag);
|
|
55619
|
+
}, "isLive");
|
|
55620
|
+
const found2 = await findIndexedHookCreatedEvent(basedir, index, (event) => isMatchingHookCreatedEvent(event, matches) && isLive(event), tag);
|
|
55621
|
+
return found2 && isMatchingHookCreatedEvent(found2, matches) ? found2 : null;
|
|
55490
55622
|
}
|
|
55491
55623
|
async function restoreHookCachesFromEvent(basedir, event, tag) {
|
|
55492
55624
|
const hook = hookFromCreatedEvent(event);
|
|
@@ -55496,7 +55628,8 @@ async function restoreHookCachesFromEvent(basedir, event, tag) {
|
|
|
55496
55628
|
hookId: hook.hookId,
|
|
55497
55629
|
runId: hook.runId,
|
|
55498
55630
|
eventId: event.eventId,
|
|
55499
|
-
tokenRetentionUntil: event.eventData.tokenRetentionUntil
|
|
55631
|
+
tokenRetentionUntil: event.eventData.tokenRetentionUntil,
|
|
55632
|
+
...hook.claimedFrom && { claimedFrom: hook.claimedFrom }
|
|
55500
55633
|
}));
|
|
55501
55634
|
await writeHookByRunMarker(basedir, hook.runId, hook.hookId, tag);
|
|
55502
55635
|
await writeExclusive(taggedPath(basedir, "hooks", hook.hookId, tag), JSON.stringify(hook, jsonReplacer, 2));
|
|
@@ -55521,36 +55654,53 @@ function createHooksStorage(basedir, tag) {
|
|
|
55521
55654
|
return !await isTerminalRunCache(basedir, hook.runId, tag);
|
|
55522
55655
|
}
|
|
55523
55656
|
__name(isHookAvailable, "isHookAvailable");
|
|
55657
|
+
async function isForceDisposed(hook) {
|
|
55658
|
+
const lock2 = await readHookDisposeLock(basedir, hook.hookId, tag);
|
|
55659
|
+
return lock2.committed && lock2.forceClaimedBy !== void 0;
|
|
55660
|
+
}
|
|
55661
|
+
__name(isForceDisposed, "isForceDisposed");
|
|
55524
55662
|
async function findHookByToken(token) {
|
|
55525
55663
|
const claim3 = await readHookTokenClaim(hookTokenClaimPath(basedir, token));
|
|
55526
55664
|
if (claim3?.hookId) {
|
|
55527
55665
|
try {
|
|
55528
55666
|
const hook = await readJSONWithFallback(basedir, "hooks", claim3.hookId, HookSchema2, tag);
|
|
55529
55667
|
if (hook?.token === token) {
|
|
55530
|
-
if (
|
|
55668
|
+
if (await isHookAvailable(hook)) {
|
|
55669
|
+
return { ...hook, isWebhook: hook.isWebhook ?? true };
|
|
55670
|
+
}
|
|
55671
|
+
if (!await isForceDisposed(hook)) {
|
|
55531
55672
|
throw new HookNotFoundError2(token);
|
|
55532
55673
|
}
|
|
55533
|
-
|
|
55674
|
+
} else if (hook) {
|
|
55675
|
+
return null;
|
|
55534
55676
|
}
|
|
55535
55677
|
} catch (error121) {
|
|
55536
55678
|
if (!UnsafeEntityIdError.is(error121)) {
|
|
55537
55679
|
throw error121;
|
|
55538
55680
|
}
|
|
55681
|
+
return null;
|
|
55539
55682
|
}
|
|
55540
|
-
return null;
|
|
55541
55683
|
}
|
|
55542
55684
|
const hooksDir = path6.join(basedir, "hooks");
|
|
55543
55685
|
const files = await listJSONFiles(hooksDir);
|
|
55686
|
+
let disposedMatch = false;
|
|
55544
55687
|
for (const file3 of files) {
|
|
55545
55688
|
const hookPath = path6.join(hooksDir, `${file3}.json`);
|
|
55546
55689
|
const hook = await readJSON(hookPath, HookSchema2);
|
|
55547
55690
|
if (hook?.token === token) {
|
|
55548
|
-
if (
|
|
55549
|
-
|
|
55691
|
+
if (await isHookAvailable(hook)) {
|
|
55692
|
+
return { ...hook, isWebhook: hook.isWebhook ?? true };
|
|
55693
|
+
}
|
|
55694
|
+
if (await isForceDisposed(hook)) {
|
|
55695
|
+
disposedMatch = true;
|
|
55696
|
+
continue;
|
|
55550
55697
|
}
|
|
55551
|
-
|
|
55698
|
+
throw new HookNotFoundError2(token);
|
|
55552
55699
|
}
|
|
55553
55700
|
}
|
|
55701
|
+
if (disposedMatch) {
|
|
55702
|
+
throw new HookNotFoundError2(token);
|
|
55703
|
+
}
|
|
55554
55704
|
return null;
|
|
55555
55705
|
}
|
|
55556
55706
|
__name(findHookByToken, "findHookByToken");
|
|
@@ -56816,6 +56966,16 @@ function createEventsStorage(basedir, tag) {
|
|
|
56816
56966
|
}
|
|
56817
56967
|
}
|
|
56818
56968
|
__name(storeEvent, "storeEvent");
|
|
56969
|
+
async function refuseDisposedHookDelivery(hookId, token) {
|
|
56970
|
+
const lock2 = await readHookDisposeLock(basedir, hookId, tag);
|
|
56971
|
+
if (!lock2.committed)
|
|
56972
|
+
return;
|
|
56973
|
+
if (lock2.forceClaimedBy) {
|
|
56974
|
+
throw new HookForceClaimedError2(typeof token === "string" ? token : "", lock2.forceClaimedBy.runId, lock2.forceClaimedBy.hookId);
|
|
56975
|
+
}
|
|
56976
|
+
throw new HookNotFoundError2(hookId);
|
|
56977
|
+
}
|
|
56978
|
+
__name(refuseDisposedHookDelivery, "refuseDisposedHookDelivery");
|
|
56819
56979
|
const queryRunEvents = /* @__PURE__ */ __name((runId, pagination) => paginatedFileSystemQuery({
|
|
56820
56980
|
directory: path10.join(basedir, "events"),
|
|
56821
56981
|
schema: ReadEventSchema,
|
|
@@ -57006,8 +57166,8 @@ function createEventsStorage(basedir, tag) {
|
|
|
57006
57166
|
}
|
|
57007
57167
|
}
|
|
57008
57168
|
}
|
|
57009
|
-
if (data.eventType === "hook_received"
|
|
57010
|
-
|
|
57169
|
+
if (data.eventType === "hook_received") {
|
|
57170
|
+
await refuseDisposedHookDelivery(data.correlationId, data.eventData?.token);
|
|
57011
57171
|
}
|
|
57012
57172
|
const existingHook = await readJSONWithFallback(basedir, "hooks", data.correlationId, HookSchema2, tag);
|
|
57013
57173
|
if (!existingHook) {
|
|
@@ -57066,6 +57226,7 @@ function createEventsStorage(basedir, tag) {
|
|
|
57066
57226
|
}
|
|
57067
57227
|
}
|
|
57068
57228
|
}
|
|
57229
|
+
let prePublishedEvent;
|
|
57069
57230
|
let event = {
|
|
57070
57231
|
...data,
|
|
57071
57232
|
runId: effectiveRunId,
|
|
@@ -57437,13 +57598,15 @@ function createEventsStorage(basedir, tag) {
|
|
|
57437
57598
|
) {
|
|
57438
57599
|
const hookData = data.eventData;
|
|
57439
57600
|
const constraintPath = hookTokenClaimPath(basedir, hookData.token);
|
|
57440
|
-
|
|
57601
|
+
let claimedFrom;
|
|
57602
|
+
const claimContent = /* @__PURE__ */ __name(() => JSON.stringify({
|
|
57441
57603
|
token: hookData.token,
|
|
57442
57604
|
hookId: data.correlationId,
|
|
57443
57605
|
runId: effectiveRunId,
|
|
57444
57606
|
eventId,
|
|
57445
|
-
tokenRetentionUntil: hookData.tokenRetentionUntil
|
|
57446
|
-
|
|
57607
|
+
tokenRetentionUntil: hookData.tokenRetentionUntil,
|
|
57608
|
+
...claimedFrom && { claimedFrom }
|
|
57609
|
+
}), "claimContent");
|
|
57447
57610
|
const claimResult = await withHookTokenClaimLock(basedir, hookData.token, async (signal) => {
|
|
57448
57611
|
let existingClaim = await readHookTokenClaim(constraintPath);
|
|
57449
57612
|
if (!existingClaim) {
|
|
@@ -57454,26 +57617,114 @@ function createEventsStorage(basedir, tag) {
|
|
|
57454
57617
|
}
|
|
57455
57618
|
if (!existingClaim) {
|
|
57456
57619
|
signal.throwIfAborted();
|
|
57457
|
-
assert3(await writeExclusive(constraintPath, claimContent));
|
|
57620
|
+
assert3(await writeExclusive(constraintPath, claimContent()));
|
|
57458
57621
|
return { status: "claimed" };
|
|
57459
57622
|
}
|
|
57460
57623
|
if (existingClaim.runId === effectiveRunId && existingClaim.hookId === data.correlationId) {
|
|
57461
57624
|
return { status: "owned", claim: existingClaim };
|
|
57462
57625
|
}
|
|
57463
57626
|
if (!await isHookTokenClaimReleasable(basedir, existingClaim, tag)) {
|
|
57464
|
-
|
|
57627
|
+
if (hookData.force !== true || !existingClaim.hookId) {
|
|
57628
|
+
return { status: "conflict", claim: existingClaim };
|
|
57629
|
+
}
|
|
57630
|
+
signal.throwIfAborted();
|
|
57631
|
+
const victimRun = await readJSONWithFallback(basedir, "runs", existingClaim.runId, WorkflowRunSchema2, tag);
|
|
57632
|
+
const victimRunning = victimRun !== null && !isTerminalWorkflowRunStatus2(victimRun.status);
|
|
57633
|
+
claimedFrom = {
|
|
57634
|
+
runId: existingClaim.runId,
|
|
57635
|
+
hookId: existingClaim.hookId,
|
|
57636
|
+
...victimRunning && {
|
|
57637
|
+
workflowName: victimRun.workflowName,
|
|
57638
|
+
deploymentId: victimRun.deploymentId,
|
|
57639
|
+
runSpecVersion: victimRun.specVersion
|
|
57640
|
+
}
|
|
57641
|
+
};
|
|
57642
|
+
if (victimRunning && (victimRun.specVersion ?? SPEC_VERSION_LEGACY2) < SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM2) {
|
|
57643
|
+
return {
|
|
57644
|
+
status: "conflict",
|
|
57645
|
+
claim: existingClaim,
|
|
57646
|
+
forceRefusedReason: "victim-spec-version"
|
|
57647
|
+
};
|
|
57648
|
+
}
|
|
57649
|
+
const journaledEventId = await findExistingHookCreatedEventId(basedir, effectiveRunId, data.correlationId);
|
|
57650
|
+
if (journaledEventId) {
|
|
57651
|
+
eventId = journaledEventId;
|
|
57652
|
+
prePublishedEvent = { ...event, eventId };
|
|
57653
|
+
} else {
|
|
57654
|
+
prePublishedEvent = await storeEvent({
|
|
57655
|
+
...event,
|
|
57656
|
+
eventData: {
|
|
57657
|
+
...event.eventData,
|
|
57658
|
+
forceClaimedFrom: claimedFrom
|
|
57659
|
+
}
|
|
57660
|
+
});
|
|
57661
|
+
eventId = prePublishedEvent.eventId;
|
|
57662
|
+
}
|
|
57663
|
+
await writeHookByRunMarker(basedir, effectiveRunId, data.correlationId, tag);
|
|
57664
|
+
await writeJSON(taggedPath(basedir, "hooks", data.correlationId, tag), {
|
|
57665
|
+
runId: effectiveRunId,
|
|
57666
|
+
hookId: data.correlationId,
|
|
57667
|
+
token: hookData.token,
|
|
57668
|
+
metadata: hookData.metadata,
|
|
57669
|
+
ownerId: "local-owner",
|
|
57670
|
+
projectId: "local-project",
|
|
57671
|
+
environment: "local",
|
|
57672
|
+
createdAt: now2,
|
|
57673
|
+
specVersion: effectiveSpecVersion,
|
|
57674
|
+
isWebhook: hookData.isWebhook ?? false,
|
|
57675
|
+
isSystem: hookData.isSystem ?? false,
|
|
57676
|
+
tokenRetentionUntil: hookData.tokenRetentionUntil,
|
|
57677
|
+
claimedFrom
|
|
57678
|
+
}, { overwrite: true });
|
|
57679
|
+
const lockWritten = await writeExclusive(hookDisposeLockPath(basedir, existingClaim.hookId, tag), JSON.stringify({
|
|
57680
|
+
forceClaimedBy: {
|
|
57681
|
+
runId: effectiveRunId,
|
|
57682
|
+
hookId: data.correlationId
|
|
57683
|
+
}
|
|
57684
|
+
}));
|
|
57685
|
+
if (victimRunning) {
|
|
57686
|
+
if (lockWritten) {
|
|
57687
|
+
const disposedEvent = {
|
|
57688
|
+
eventType: "hook_disposed",
|
|
57689
|
+
correlationId: existingClaim.hookId,
|
|
57690
|
+
eventData: {
|
|
57691
|
+
token: hookData.token,
|
|
57692
|
+
forceClaimedBy: {
|
|
57693
|
+
runId: effectiveRunId,
|
|
57694
|
+
hookId: data.correlationId
|
|
57695
|
+
}
|
|
57696
|
+
},
|
|
57697
|
+
runId: existingClaim.runId,
|
|
57698
|
+
eventId: await mintEventId(existingClaim.runId),
|
|
57699
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
57700
|
+
specVersion: victimRun.specVersion
|
|
57701
|
+
};
|
|
57702
|
+
await storeEvent(disposedEvent);
|
|
57703
|
+
}
|
|
57704
|
+
}
|
|
57465
57705
|
}
|
|
57466
57706
|
signal.throwIfAborted();
|
|
57467
|
-
|
|
57707
|
+
if (claimedFrom) {
|
|
57708
|
+
await write(constraintPath, claimContent(), {
|
|
57709
|
+
overwrite: true
|
|
57710
|
+
});
|
|
57711
|
+
} else {
|
|
57712
|
+
await deleteJSON(constraintPath);
|
|
57713
|
+
}
|
|
57468
57714
|
if (existingClaim.hookId) {
|
|
57469
57715
|
await deleteJSON(taggedPath(basedir, "hooks", existingClaim.hookId, tag));
|
|
57470
57716
|
await deleteJSON(hookRecoveryMarkerPath(basedir, hookData.token, existingClaim.runId, existingClaim.hookId));
|
|
57471
57717
|
await deleteHookByRunMarker(basedir, existingClaim.runId, existingClaim.hookId, tag);
|
|
57472
57718
|
}
|
|
57473
57719
|
signal.throwIfAborted();
|
|
57474
|
-
|
|
57720
|
+
if (!claimedFrom) {
|
|
57721
|
+
assert3(await writeExclusive(constraintPath, claimContent()));
|
|
57722
|
+
}
|
|
57475
57723
|
return { status: "claimed" };
|
|
57476
57724
|
});
|
|
57725
|
+
if (claimResult.status === "owned" && claimResult.claim.claimedFrom) {
|
|
57726
|
+
claimedFrom = claimResult.claim.claimedFrom;
|
|
57727
|
+
}
|
|
57477
57728
|
if (claimResult.status === "owned") {
|
|
57478
57729
|
const existingClaim = claimResult.claim;
|
|
57479
57730
|
let canonicalEventId;
|
|
@@ -57515,7 +57766,10 @@ function createEventsStorage(basedir, tag) {
|
|
|
57515
57766
|
correlationId: data.correlationId,
|
|
57516
57767
|
eventData: {
|
|
57517
57768
|
token: hookData.token,
|
|
57518
|
-
conflictingRunId: existingClaim.runId
|
|
57769
|
+
conflictingRunId: existingClaim.runId,
|
|
57770
|
+
...claimResult.forceRefusedReason !== void 0 && {
|
|
57771
|
+
forceRefusedReason: claimResult.forceRefusedReason
|
|
57772
|
+
}
|
|
57519
57773
|
},
|
|
57520
57774
|
runId: effectiveRunId,
|
|
57521
57775
|
eventId,
|
|
@@ -57543,6 +57797,18 @@ function createEventsStorage(basedir, tag) {
|
|
|
57543
57797
|
hasMore: conflictDelta.hasMore
|
|
57544
57798
|
};
|
|
57545
57799
|
}
|
|
57800
|
+
if (claimedFrom) {
|
|
57801
|
+
event = {
|
|
57802
|
+
...event,
|
|
57803
|
+
eventData: {
|
|
57804
|
+
...event.eventData,
|
|
57805
|
+
// Wake-targeting fields included: a replay of this run
|
|
57806
|
+
// republishes the victim's wake from this row alone when the
|
|
57807
|
+
// invocation that created the hook died before waking it.
|
|
57808
|
+
forceClaimedFrom: claimedFrom
|
|
57809
|
+
}
|
|
57810
|
+
};
|
|
57811
|
+
}
|
|
57546
57812
|
const persistedHookData = event.eventData;
|
|
57547
57813
|
hook = {
|
|
57548
57814
|
runId: effectiveRunId,
|
|
@@ -57557,9 +57823,10 @@ function createEventsStorage(basedir, tag) {
|
|
|
57557
57823
|
specVersion: effectiveSpecVersion,
|
|
57558
57824
|
isWebhook: persistedHookData.isWebhook ?? false,
|
|
57559
57825
|
isSystem: persistedHookData.isSystem ?? false,
|
|
57560
|
-
tokenRetentionUntil: persistedHookData.tokenRetentionUntil
|
|
57826
|
+
tokenRetentionUntil: persistedHookData.tokenRetentionUntil,
|
|
57827
|
+
...claimedFrom && { claimedFrom }
|
|
57561
57828
|
};
|
|
57562
|
-
hookEntityWriteOptions = claimResult.status === "owned" ? { overwrite: true } : void 0;
|
|
57829
|
+
hookEntityWriteOptions = claimResult.status === "owned" || claimedFrom ? { overwrite: true } : void 0;
|
|
57563
57830
|
await writeHookCreatedIndexEntries(basedir, hookData.token, effectiveRunId, data.correlationId, eventId, tag);
|
|
57564
57831
|
} else if (data.eventType === "hook_disposed") {
|
|
57565
57832
|
const lockPath = hookDisposeLockPath(basedir, data.correlationId, tag);
|
|
@@ -57617,8 +57884,14 @@ function createEventsStorage(basedir, tag) {
|
|
|
57617
57884
|
};
|
|
57618
57885
|
await writeJSON(taggedPath(basedir, "waits", waitCompositeKey, tag), wait, { overwrite: true });
|
|
57619
57886
|
}
|
|
57620
|
-
if (data.eventType === "hook_received" && data.correlationId
|
|
57621
|
-
|
|
57887
|
+
if (data.eventType === "hook_received" && data.correlationId) {
|
|
57888
|
+
await refuseDisposedHookDelivery(data.correlationId, data.eventData?.token);
|
|
57889
|
+
}
|
|
57890
|
+
if (data.eventType === "hook_created" && data.correlationId) {
|
|
57891
|
+
const own3 = await readHookDisposeLock(basedir, data.correlationId, tag);
|
|
57892
|
+
if (own3.committed && own3.forceClaimedBy) {
|
|
57893
|
+
throw new EntityConflictError2(`Hook "${data.correlationId}" was force-claimed by another run before its creation was journaled`);
|
|
57894
|
+
}
|
|
57622
57895
|
}
|
|
57623
57896
|
let eventPath = taggedPath(basedir, "events", `${effectiveRunId}-${eventId}`, tag);
|
|
57624
57897
|
let serializedEvent = JSON.stringify(event, jsonReplacer, 2);
|
|
@@ -57641,7 +57914,13 @@ function createEventsStorage(basedir, tag) {
|
|
|
57641
57914
|
return true;
|
|
57642
57915
|
}, "bumpEventSlot");
|
|
57643
57916
|
let eventPublished = false;
|
|
57644
|
-
|
|
57917
|
+
if (prePublishedEvent) {
|
|
57918
|
+
event = prePublishedEvent;
|
|
57919
|
+
eventPath = taggedPath(basedir, "events", `${effectiveRunId}-${eventId}`, tag);
|
|
57920
|
+
serializedEvent = JSON.stringify(event, jsonReplacer, 2);
|
|
57921
|
+
eventPublished = true;
|
|
57922
|
+
}
|
|
57923
|
+
for (let attempt = 0; !eventPublished; attempt++) {
|
|
57645
57924
|
if (data.eventType === "hook_received") {
|
|
57646
57925
|
const terminalByMarker = await isRunTerminalCommitted(basedir, effectiveRunId, tag);
|
|
57647
57926
|
const runNow = terminalByMarker ? null : await readJSONWithFallback(basedir, "runs", effectiveRunId, WorkflowRunSchema2, tag);
|
|
@@ -58010,7 +58289,11 @@ function createWorld(args) {
|
|
|
58010
58289
|
// `(runId, resumeId)` via a filesystem sidecar claim (see
|
|
58011
58290
|
// events-storage.ts `claimHookResume`), so resumeHook()'s parallel fast
|
|
58012
58291
|
// path converges on one event in dev exactly as it does on Vercel.
|
|
58013
|
-
hookResumeDedup: true
|
|
58292
|
+
hookResumeDedup: true,
|
|
58293
|
+
// The token claim lock serializes the takeover behind
|
|
58294
|
+
// `createHook({ experimental_force: true })`; see the hook_created
|
|
58295
|
+
// branch of storage/events-storage.ts.
|
|
58296
|
+
hookForceClaim: true
|
|
58014
58297
|
},
|
|
58015
58298
|
...queue,
|
|
58016
58299
|
...storage,
|
|
@@ -61842,7 +62125,7 @@ var version4;
|
|
|
61842
62125
|
var init_version3 = __esm({
|
|
61843
62126
|
"../world-vercel/dist/version.js"() {
|
|
61844
62127
|
"use strict";
|
|
61845
|
-
version4 = "5.0.0-beta.
|
|
62128
|
+
version4 = "5.0.0-beta.51";
|
|
61846
62129
|
}
|
|
61847
62130
|
});
|
|
61848
62131
|
|
|
@@ -62424,6 +62707,10 @@ function headersToRecord(headers) {
|
|
|
62424
62707
|
}
|
|
62425
62708
|
function errorForResponse(status, message, opts = {}) {
|
|
62426
62709
|
const { retryAfter, code: code3, url: url3, mitigated, details } = opts;
|
|
62710
|
+
if (status === 409 && code3 === "hook-force-claimed") {
|
|
62711
|
+
const claimedBy = details && typeof details === "object" ? details.claimedBy : void 0;
|
|
62712
|
+
return new HookForceClaimedError2("", typeof claimedBy?.runId === "string" ? claimedBy.runId : "unknown", typeof claimedBy?.hookId === "string" ? claimedBy.hookId : void 0);
|
|
62713
|
+
}
|
|
62427
62714
|
if (status === 409)
|
|
62428
62715
|
return new EntityConflictError2(message);
|
|
62429
62716
|
if (status === 410) {
|
|
@@ -74579,10 +74866,20 @@ function toBatchResult(outcome) {
|
|
|
74579
74866
|
messageId: outcome.messageId ? MessageId2.parse(outcome.messageId) : null
|
|
74580
74867
|
};
|
|
74581
74868
|
}
|
|
74582
|
-
function
|
|
74869
|
+
function getErrorRetryAfterSeconds(error121) {
|
|
74870
|
+
if (typeof error121 !== "object" || error121 === null)
|
|
74871
|
+
return void 0;
|
|
74872
|
+
const retryAfter = error121.retryAfter;
|
|
74873
|
+
if (typeof retryAfter !== "number" || !Number.isFinite(retryAfter) || retryAfter <= 0) {
|
|
74874
|
+
return void 0;
|
|
74875
|
+
}
|
|
74876
|
+
return Math.min(Math.ceil(retryAfter), HANDLER_ERROR_MAX_RETRY_AFTER_SECONDS);
|
|
74877
|
+
}
|
|
74878
|
+
function getHandlerErrorRetryAfterSeconds(error121, deliveryCount) {
|
|
74583
74879
|
const backoffSeconds = Math.min(Math.max(HANDLER_ERROR_RETRY_AFTER_SECONDS, 2 ** (deliveryCount - 1)), HANDLER_ERROR_MAX_RETRY_AFTER_SECONDS);
|
|
74584
74880
|
const jitterSeconds = Math.floor(Math.random() * (Math.ceil(backoffSeconds * HANDLER_ERROR_RETRY_JITTER_RATIO) + 1));
|
|
74585
|
-
|
|
74881
|
+
const jitteredBackoffSeconds = Math.max(HANDLER_ERROR_RETRY_AFTER_SECONDS, backoffSeconds - jitterSeconds);
|
|
74882
|
+
return Math.max(jitteredBackoffSeconds, getErrorRetryAfterSeconds(error121) ?? HANDLER_ERROR_RETRY_AFTER_SECONDS);
|
|
74586
74883
|
}
|
|
74587
74884
|
function getRunIdFromPayload(payload) {
|
|
74588
74885
|
if ("runId" in payload && typeof payload.runId === "string") {
|
|
@@ -74800,7 +75097,7 @@ function createQueue2(config4) {
|
|
|
74800
75097
|
// redrive in lockstep. Workflow handlers are event-sourced and must
|
|
74801
75098
|
// remain idempotent because queue retries can happen close together.
|
|
74802
75099
|
retry: /* @__PURE__ */ __name((error121, { messageId, deliveryCount }) => {
|
|
74803
|
-
const afterSeconds = getHandlerErrorRetryAfterSeconds(deliveryCount);
|
|
75100
|
+
const afterSeconds = getHandlerErrorRetryAfterSeconds(error121, deliveryCount);
|
|
74804
75101
|
console.error(`[workflow] Queue handler failed for message "${messageId}" on delivery attempt ${deliveryCount}; retrying in ${afterSeconds}s:`, error121);
|
|
74805
75102
|
return { afterSeconds };
|
|
74806
75103
|
}, "retry")
|
|
@@ -74931,6 +75228,7 @@ var init_queue4 = __esm({
|
|
|
74931
75228
|
HANDLER_ERROR_RETRY_AFTER_SECONDS = 1;
|
|
74932
75229
|
HANDLER_ERROR_MAX_RETRY_AFTER_SECONDS = 900;
|
|
74933
75230
|
HANDLER_ERROR_RETRY_JITTER_RATIO = 0.25;
|
|
75231
|
+
__name(getErrorRetryAfterSeconds, "getErrorRetryAfterSeconds");
|
|
74934
75232
|
__name(getHandlerErrorRetryAfterSeconds, "getHandlerErrorRetryAfterSeconds");
|
|
74935
75233
|
FALLBACK_REGION = "iad1";
|
|
74936
75234
|
__name(getRunIdFromPayload, "getRunIdFromPayload");
|
|
@@ -75063,7 +75361,9 @@ function collectErrorMarkers(err, depth = 0) {
|
|
|
75063
75361
|
function isRetryableEventPostError(err) {
|
|
75064
75362
|
if (err instanceof ReplayEventObserverError)
|
|
75065
75363
|
return false;
|
|
75066
|
-
if (EntityConflictError2.is(err) ||
|
|
75364
|
+
if (EntityConflictError2.is(err) || // A takeover redirect is definitive for THIS target; the runtime's
|
|
75365
|
+
// resume path follows the token instead of re-issuing the write here.
|
|
75366
|
+
HookForceClaimedError2.is(err) || RunExpiredError2.is(err) || TooEarlyError.is(err) || ThrottleError2.is(err)) {
|
|
75067
75367
|
return false;
|
|
75068
75368
|
}
|
|
75069
75369
|
if (WorkflowWorldError2.is(err) || StreamError2.is(err)) {
|
|
@@ -75592,6 +75892,8 @@ function buildPostFrameMeta(input3) {
|
|
|
75592
75892
|
meta5.hookIsWebhook = input3.hookIsWebhook;
|
|
75593
75893
|
if (input3.hookIsSystem !== void 0)
|
|
75594
75894
|
meta5.hookIsSystem = input3.hookIsSystem;
|
|
75895
|
+
if (input3.hookForce !== void 0)
|
|
75896
|
+
meta5.hookForce = input3.hookForce;
|
|
75595
75897
|
if (input3.resumeId !== void 0)
|
|
75596
75898
|
meta5.resumeId = input3.resumeId;
|
|
75597
75899
|
if (input3.errorCode !== void 0)
|
|
@@ -75659,8 +75961,13 @@ function errorFromV4Response(statusCode, responseHeaders, errorBody, opName, url
|
|
|
75659
75961
|
message = record3.message;
|
|
75660
75962
|
if (typeof record3.code === "string")
|
|
75661
75963
|
code3 = record3.code;
|
|
75964
|
+
else if (typeof record3.error === "string")
|
|
75965
|
+
code3 = record3.error;
|
|
75662
75966
|
if (statusCode === 412)
|
|
75663
75967
|
details = decodePreconditionDetails(record3);
|
|
75968
|
+
if (statusCode === 409 && code3 === "hook-force-claimed") {
|
|
75969
|
+
details = { claimedBy: record3.claimedBy };
|
|
75970
|
+
}
|
|
75664
75971
|
} else if (text) {
|
|
75665
75972
|
message += ` ${text}`;
|
|
75666
75973
|
}
|
|
@@ -76634,6 +76941,9 @@ function splitEventDataForV4(data) {
|
|
|
76634
76941
|
if (typeof eventData.isSystem === "boolean") {
|
|
76635
76942
|
meta5.hookIsSystem = eventData.isSystem;
|
|
76636
76943
|
}
|
|
76944
|
+
if (eventData.force === true) {
|
|
76945
|
+
meta5.hookForce = true;
|
|
76946
|
+
}
|
|
76637
76947
|
if (typeof eventData.errorCode === "string") {
|
|
76638
76948
|
meta5.errorCode = eventData.errorCode;
|
|
76639
76949
|
}
|
|
@@ -76786,6 +77096,10 @@ async function createWorkflowRunEvent(id, data, params, config4) {
|
|
|
76786
77096
|
} catch (err) {
|
|
76787
77097
|
if (err instanceof ReplayEventObserverError)
|
|
76788
77098
|
throw err.error;
|
|
77099
|
+
if (HookForceClaimedError2.is(err) && data.eventType === "hook_received") {
|
|
77100
|
+
const token = data.eventData?.token;
|
|
77101
|
+
throw new HookForceClaimedError2(typeof token === "string" ? token : err.token, err.claimedByRunId, err.claimedByHookId);
|
|
77102
|
+
}
|
|
76789
77103
|
if (isHookEventRequiringExistence(data.eventType) && WorkflowWorldError2.is(err) && err.status === 404 && data.correlationId) {
|
|
76790
77104
|
throw new HookNotFoundError2(data.correlationId);
|
|
76791
77105
|
}
|
|
@@ -78258,7 +78572,15 @@ function createWorld2(config4) {
|
|
|
78258
78572
|
maxConcurrency: true,
|
|
78259
78573
|
// Vercel deployments are atomic and immutable, so a deployment id names
|
|
78260
78574
|
// one fixed build for its whole lifetime.
|
|
78261
|
-
deploymentAffinity: true
|
|
78575
|
+
deploymentAffinity: true,
|
|
78576
|
+
// The server implements the takeover protocol behind
|
|
78577
|
+
// `createHook({ experimental_force: true })` (workflow-server
|
|
78578
|
+
// docs/hook-force-claim.md). Static rather than attested per lookup,
|
|
78579
|
+
// because the decision is made at `createHook()` time, before any
|
|
78580
|
+
// lookup; against a server that has it switched off (or predates it)
|
|
78581
|
+
// a forced creation is answered with `hook_conflict`, which the
|
|
78582
|
+
// runtime reports as an unsupported-World failure rather than a win.
|
|
78583
|
+
hookForceClaim: true
|
|
78262
78584
|
// NOTE: the backend half of resumeHook()'s lazy path (that
|
|
78263
78585
|
// the server enforces the `(runId, resumeId)` dedup constraint) is
|
|
78264
78586
|
// NO LONGER a static world capability here. It is attested per-lookup by
|
|
@@ -82220,6 +82542,21 @@ function getCommonReducers2(_global2 = globalThis) {
|
|
|
82220
82542
|
}
|
|
82221
82543
|
return reduced;
|
|
82222
82544
|
}, "HookConflictError"),
|
|
82545
|
+
HookForceClaimedError: /* @__PURE__ */ __name((value) => {
|
|
82546
|
+
const base = reduceNamedErrorSubclassBase2("HookForceClaimedError", value);
|
|
82547
|
+
if (!base)
|
|
82548
|
+
return false;
|
|
82549
|
+
const reduced = {
|
|
82550
|
+
...base,
|
|
82551
|
+
token: readProperty2(value, "token"),
|
|
82552
|
+
claimedByRunId: readProperty2(value, "claimedByRunId")
|
|
82553
|
+
};
|
|
82554
|
+
const claimedByHookId = readProperty2(value, "claimedByHookId");
|
|
82555
|
+
if (claimedByHookId !== void 0) {
|
|
82556
|
+
reduced.claimedByHookId = claimedByHookId;
|
|
82557
|
+
}
|
|
82558
|
+
return reduced;
|
|
82559
|
+
}, "HookForceClaimedError"),
|
|
82223
82560
|
RangeError: makeErrorSubclassReducer2("RangeError"),
|
|
82224
82561
|
ReferenceError: makeErrorSubclassReducer2("ReferenceError"),
|
|
82225
82562
|
// RetryableError carries an extra `retryAfter` Date that we serialize as
|
|
@@ -82404,6 +82741,16 @@ function getCommonRevivers3(global2 = globalThis) {
|
|
|
82404
82741
|
}
|
|
82405
82742
|
return error121;
|
|
82406
82743
|
}, "HookConflictError"),
|
|
82744
|
+
HookForceClaimedError: /* @__PURE__ */ __name((value) => {
|
|
82745
|
+
const Ctor = global2[/* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError")] ?? HookForceClaimedError2;
|
|
82746
|
+
const error121 = new Ctor(value.token, value.claimedByRunId, value.claimedByHookId);
|
|
82747
|
+
if (value.stack !== void 0)
|
|
82748
|
+
error121.stack = value.stack;
|
|
82749
|
+
if ("cause" in value) {
|
|
82750
|
+
error121.cause = value.cause;
|
|
82751
|
+
}
|
|
82752
|
+
return error121;
|
|
82753
|
+
}, "HookForceClaimedError"),
|
|
82407
82754
|
RangeError: makeErrorSubclassReviver2(global2, "RangeError"),
|
|
82408
82755
|
ReferenceError: makeErrorSubclassReviver2(global2, "ReferenceError"),
|
|
82409
82756
|
RetryableError: /* @__PURE__ */ __name((value) => {
|
|
@@ -86041,7 +86388,7 @@ var version5;
|
|
|
86041
86388
|
var init_version4 = __esm({
|
|
86042
86389
|
"../core/dist/version.js"() {
|
|
86043
86390
|
"use strict";
|
|
86044
|
-
version5 = "5.0.0-beta.
|
|
86391
|
+
version5 = "5.0.0-beta.56";
|
|
86045
86392
|
}
|
|
86046
86393
|
});
|
|
86047
86394
|
|
|
@@ -86512,6 +86859,112 @@ var init_helpers3 = __esm({
|
|
|
86512
86859
|
}
|
|
86513
86860
|
});
|
|
86514
86861
|
|
|
86862
|
+
// ../core/dist/runtime/hook-wake.js
|
|
86863
|
+
function isRetryableWakeError2(error121, isDeploymentUnavailableError) {
|
|
86864
|
+
if (isDeploymentUnavailableError?.(error121))
|
|
86865
|
+
return false;
|
|
86866
|
+
const status = error121 ?? {};
|
|
86867
|
+
const code3 = status.status ?? status.statusCode;
|
|
86868
|
+
if (typeof code3 === "number") {
|
|
86869
|
+
return code3 >= 500 || code3 === 408 || code3 === 429;
|
|
86870
|
+
}
|
|
86871
|
+
const name = error121?.name;
|
|
86872
|
+
return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
|
|
86873
|
+
}
|
|
86874
|
+
async function publishHookWakeWithRetry2(publish, isDeploymentUnavailableError) {
|
|
86875
|
+
let lastError;
|
|
86876
|
+
for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS2.length; attempt++) {
|
|
86877
|
+
try {
|
|
86878
|
+
await publish();
|
|
86879
|
+
return;
|
|
86880
|
+
} catch (error121) {
|
|
86881
|
+
lastError = error121;
|
|
86882
|
+
if (!isRetryableWakeError2(error121, isDeploymentUnavailableError))
|
|
86883
|
+
break;
|
|
86884
|
+
const delayMs = HOOK_WAKE_RETRY_DELAYS_MS2[attempt];
|
|
86885
|
+
if (delayMs !== void 0) {
|
|
86886
|
+
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
86887
|
+
}
|
|
86888
|
+
}
|
|
86889
|
+
}
|
|
86890
|
+
if (HookNotFoundError2.is(lastError)) {
|
|
86891
|
+
throw new WorkflowRuntimeError2("The hook resume was committed, but its workflow wake could not be published", { cause: lastError });
|
|
86892
|
+
}
|
|
86893
|
+
throw lastError;
|
|
86894
|
+
}
|
|
86895
|
+
async function publishForceClaimVictimWake(world, claimerRunId, hook) {
|
|
86896
|
+
const from = hook.claimedFrom;
|
|
86897
|
+
if (!from || from.runId === claimerRunId)
|
|
86898
|
+
return "skipped";
|
|
86899
|
+
if (from.workflowName === void 0) {
|
|
86900
|
+
runtimeLogger2.warn("Force-claimed a hook from a run whose workflow name is unknown; not waking it", { workflowRunId: claimerRunId, victimRunId: from.runId });
|
|
86901
|
+
return "skipped";
|
|
86902
|
+
}
|
|
86903
|
+
try {
|
|
86904
|
+
await publishHookWakeWithRetry2(() => world.queue(getWorkflowQueueName2(from.workflowName), { runId: from.runId }, {
|
|
86905
|
+
...from.deploymentId !== void 0 && {
|
|
86906
|
+
deploymentId: from.deploymentId
|
|
86907
|
+
},
|
|
86908
|
+
specVersion: from.runSpecVersion ?? SPEC_VERSION_LEGACY2,
|
|
86909
|
+
idempotencyKey: `hook-force-claim-${hook.hookId}`
|
|
86910
|
+
}), world.isDeploymentUnavailableError?.bind(world));
|
|
86911
|
+
return "published";
|
|
86912
|
+
} catch (error121) {
|
|
86913
|
+
runtimeLogger2.error("Force-claimed a hook token but could not wake the run it was taken from; it will read the disposal on its next invocation", {
|
|
86914
|
+
workflowRunId: claimerRunId,
|
|
86915
|
+
victimRunId: from.runId,
|
|
86916
|
+
error: error121 instanceof Error ? error121.message : String(error121)
|
|
86917
|
+
});
|
|
86918
|
+
return "failed";
|
|
86919
|
+
}
|
|
86920
|
+
}
|
|
86921
|
+
function forcedCreationOwingWake(events) {
|
|
86922
|
+
if (!events)
|
|
86923
|
+
return void 0;
|
|
86924
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
86925
|
+
const event = events[i];
|
|
86926
|
+
if (event.eventType === "hook_received" || event.eventType === "noop" || event.eventType === "hook_disposed" && event.eventData?.forceClaimedBy !== void 0) {
|
|
86927
|
+
continue;
|
|
86928
|
+
}
|
|
86929
|
+
return event.eventType === "hook_created" && event.eventData.forceClaimedFrom !== void 0 ? event : void 0;
|
|
86930
|
+
}
|
|
86931
|
+
return void 0;
|
|
86932
|
+
}
|
|
86933
|
+
async function republishOwedForceClaimVictimWake(world, runId, events) {
|
|
86934
|
+
const owed = forcedCreationOwingWake(events);
|
|
86935
|
+
if (!owed)
|
|
86936
|
+
return;
|
|
86937
|
+
const claimedFrom = owed.eventData.forceClaimedFrom;
|
|
86938
|
+
const outcome = await publishForceClaimVictimWake(world, runId, {
|
|
86939
|
+
hookId: owed.correlationId,
|
|
86940
|
+
claimedFrom
|
|
86941
|
+
});
|
|
86942
|
+
if (outcome !== "skipped") {
|
|
86943
|
+
runtimeLogger2.info("Republished the wake of a force-claimed hook victim", {
|
|
86944
|
+
workflowRunId: runId,
|
|
86945
|
+
hookId: owed.correlationId,
|
|
86946
|
+
victimRunId: claimedFrom.runId,
|
|
86947
|
+
victimWake: outcome
|
|
86948
|
+
});
|
|
86949
|
+
}
|
|
86950
|
+
}
|
|
86951
|
+
var HOOK_WAKE_RETRY_DELAYS_MS2;
|
|
86952
|
+
var init_hook_wake2 = __esm({
|
|
86953
|
+
"../core/dist/runtime/hook-wake.js"() {
|
|
86954
|
+
"use strict";
|
|
86955
|
+
init_dist7();
|
|
86956
|
+
init_dist6();
|
|
86957
|
+
init_logger2();
|
|
86958
|
+
init_helpers3();
|
|
86959
|
+
HOOK_WAKE_RETRY_DELAYS_MS2 = [25, 100];
|
|
86960
|
+
__name(isRetryableWakeError2, "isRetryableWakeError");
|
|
86961
|
+
__name(publishHookWakeWithRetry2, "publishHookWakeWithRetry");
|
|
86962
|
+
__name(publishForceClaimVictimWake, "publishForceClaimVictimWake");
|
|
86963
|
+
__name(forcedCreationOwingWake, "forcedCreationOwingWake");
|
|
86964
|
+
__name(republishOwedForceClaimVictimWake, "republishOwedForceClaimVictimWake");
|
|
86965
|
+
}
|
|
86966
|
+
});
|
|
86967
|
+
|
|
86515
86968
|
// ../core/dist/runtime/invocations.js
|
|
86516
86969
|
async function handleInvocation(world, runId, requestId, payload) {
|
|
86517
86970
|
const parsed = HookInvocationSchema2.safeParse(payload);
|
|
@@ -86730,38 +87183,6 @@ async function computeResumePayloadDigest2(bytes) {
|
|
|
86730
87183
|
}
|
|
86731
87184
|
return hex5;
|
|
86732
87185
|
}
|
|
86733
|
-
function isRetryableWakeError2(error121, isDeploymentUnavailableError) {
|
|
86734
|
-
if (isDeploymentUnavailableError?.(error121))
|
|
86735
|
-
return false;
|
|
86736
|
-
const status = error121 ?? {};
|
|
86737
|
-
const code3 = status.status ?? status.statusCode;
|
|
86738
|
-
if (typeof code3 === "number") {
|
|
86739
|
-
return code3 >= 500 || code3 === 408 || code3 === 429;
|
|
86740
|
-
}
|
|
86741
|
-
const name = error121?.name;
|
|
86742
|
-
return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
|
|
86743
|
-
}
|
|
86744
|
-
async function publishHookWakeWithRetry2(publish, isDeploymentUnavailableError) {
|
|
86745
|
-
let lastError;
|
|
86746
|
-
for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS2.length; attempt++) {
|
|
86747
|
-
try {
|
|
86748
|
-
await publish();
|
|
86749
|
-
return;
|
|
86750
|
-
} catch (error121) {
|
|
86751
|
-
lastError = error121;
|
|
86752
|
-
if (!isRetryableWakeError2(error121, isDeploymentUnavailableError))
|
|
86753
|
-
break;
|
|
86754
|
-
const delayMs = HOOK_WAKE_RETRY_DELAYS_MS2[attempt];
|
|
86755
|
-
if (delayMs !== void 0) {
|
|
86756
|
-
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
86757
|
-
}
|
|
86758
|
-
}
|
|
86759
|
-
}
|
|
86760
|
-
if (HookNotFoundError2.is(lastError)) {
|
|
86761
|
-
throw new WorkflowRuntimeError2("The hook resume was committed, but its workflow wake could not be published", { cause: lastError });
|
|
86762
|
-
}
|
|
86763
|
-
throw lastError;
|
|
86764
|
-
}
|
|
86765
87186
|
function resumeContextFromRun2(run3) {
|
|
86766
87187
|
const coreVersion = run3.executionContext?.workflowCoreVersion;
|
|
86767
87188
|
const traceCarrier = run3.executionContext?.traceCarrier;
|
|
@@ -86837,154 +87258,255 @@ async function getHookByToken3(token) {
|
|
|
86837
87258
|
async function resumeHook2(tokenOrHook, payload, encryptionKeyOverride) {
|
|
86838
87259
|
return resumeHookImpl2(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
|
|
86839
87260
|
}
|
|
86840
|
-
async function resumeHookImpl2(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
|
|
87261
|
+
async function resumeHookImpl2(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, webhookOnly = false) {
|
|
86841
87262
|
return await waitedUntil2(() => {
|
|
86842
87263
|
return trace5("hook.resume", async (span) => {
|
|
86843
87264
|
const world = await getWorldLazy2();
|
|
86844
|
-
|
|
86845
|
-
|
|
86846
|
-
|
|
86847
|
-
|
|
86848
|
-
|
|
86849
|
-
|
|
86850
|
-
|
|
86851
|
-
|
|
86852
|
-
|
|
86853
|
-
|
|
86854
|
-
|
|
86855
|
-
|
|
86856
|
-
if (info.run && isTerminalWorkflowRunStatus2(info.run.status)) {
|
|
86857
|
-
throw new HookNotFoundError2(hook.token);
|
|
86858
|
-
}
|
|
86859
|
-
const capabilities = getRunCapabilities2(resumeContext.workflowCoreVersion);
|
|
86860
|
-
let payloadKey;
|
|
86861
|
-
const runPublicKey = encryptionKeyOverride ? (
|
|
86862
|
-
// The caller already holds a key (resumeWebhook resolved one to
|
|
86863
|
-
// hydrate hook metadata), so sealing would add an ECDH for no
|
|
86864
|
-
// saved round trip. Reuse what it resolved.
|
|
86865
|
-
void 0
|
|
86866
|
-
) : decodeRunPublicKey2(resumeContext.encryptionPublicKey);
|
|
86867
|
-
if (runPublicKey) {
|
|
86868
|
-
payloadKey = sealTo2(runPublicKey);
|
|
86869
|
-
} else {
|
|
86870
|
-
let encryptionKey = encryptionKeyOverride ?? await resolveHookEncryptionKey2(hook, info);
|
|
86871
|
-
if (!capabilities.supportedFormats.has(SerializationFormat2.ENCRYPTED)) {
|
|
86872
|
-
encryptionKey = void 0;
|
|
86873
|
-
}
|
|
86874
|
-
payloadKey = encryptionKey;
|
|
86875
|
-
}
|
|
86876
|
-
const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION2 && capabilities.supportedFormats.has(SerializationFormat2.GZIP);
|
|
86877
|
-
const ops = [];
|
|
86878
|
-
const readbackOps = [];
|
|
86879
|
-
const v1Compat = isLegacySpecVersion2(hook.specVersion);
|
|
86880
|
-
const dehydratedPayload = await dehydrateStepReturnValue2(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
|
|
86881
|
-
await Promise.all(ops.map((op) => op.catch((error121) => {
|
|
86882
|
-
if (error121 !== void 0)
|
|
86883
|
-
throw error121;
|
|
86884
|
-
})));
|
|
86885
|
-
safeWaitUntil2(Promise.all(readbackOps), (err) => {
|
|
86886
|
-
if (err === void 0)
|
|
86887
|
-
return;
|
|
86888
|
-
runtimeLogger2.warn("Background readback of hook payload failed", {
|
|
86889
|
-
workflowRunId: hook.runId,
|
|
86890
|
-
hookId: hook.hookId,
|
|
86891
|
-
error: err instanceof Error ? err.message : String(err)
|
|
87265
|
+
const token = typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token;
|
|
87266
|
+
let target2 = tokenOrHook;
|
|
87267
|
+
let fresh = hookFreshlyLookedUp;
|
|
87268
|
+
let keyOverride = encryptionKeyOverride;
|
|
87269
|
+
let redirects = 0;
|
|
87270
|
+
let lookupsAfterRedirect = 0;
|
|
87271
|
+
const MAX_LOOKUPS_AFTER_REDIRECT = 5;
|
|
87272
|
+
const resumeId = generateResumeId2();
|
|
87273
|
+
const assertResendable = /* @__PURE__ */ __name((cause) => {
|
|
87274
|
+
if (payload instanceof Request && payload.body !== null && payload.bodyUsed) {
|
|
87275
|
+
span?.setAttributes({
|
|
87276
|
+
"workflow.hook.resume_redirect_unresendable": true
|
|
86892
87277
|
});
|
|
86893
|
-
|
|
86894
|
-
span?.setAttributes({
|
|
86895
|
-
...WorkflowName2(resumeContext.workflowName)
|
|
86896
|
-
});
|
|
86897
|
-
const originLink = await linkToTraceCarrier2(resumeContext.traceCarrier);
|
|
86898
|
-
if (originLink) {
|
|
86899
|
-
span?.addLink?.(originLink);
|
|
87278
|
+
throw new WorkflowRuntimeError2(`Hook token "${token}" changed owner while this webhook request was being delivered; a request body can be sent only once and it was not delivered anywhere \u2014 retry the request, which will reach the token's new owner`, { cause });
|
|
86900
87279
|
}
|
|
86901
|
-
|
|
86902
|
-
|
|
86903
|
-
throw new WorkflowRuntimeError2("World advertises invoke without implementing it");
|
|
86904
|
-
}
|
|
86905
|
-
span?.setAttributes({ "workflow.hook.resume_strategy": "invoke" });
|
|
86906
|
-
const result2 = HookInvocationResultSchema2.parse(await world.invoke(hook.runId, {
|
|
86907
|
-
type: "hook_resume",
|
|
86908
|
-
version: 1,
|
|
86909
|
-
hookId: hook.hookId,
|
|
86910
|
-
token: hook.token,
|
|
86911
|
-
payload: dehydratedPayload
|
|
86912
|
-
}, { idempotencyKey: generateResumeId2() }));
|
|
86913
|
-
if (result2.status === "rejected") {
|
|
86914
|
-
if (result2.code === "HOOK_NOT_FOUND")
|
|
86915
|
-
throw new HookNotFoundError2(hook.token);
|
|
86916
|
-
throw new WorkflowRuntimeError2("Executor rejected the hook invocation input");
|
|
86917
|
-
}
|
|
86918
|
-
span?.setAttributes(HookResumeCommitted2(true));
|
|
86919
|
-
return asLazyMetadataHook2(hook);
|
|
86920
|
-
}
|
|
86921
|
-
const queueName = getWorkflowQueueName2(resumeContext.workflowName);
|
|
86922
|
-
const queueOptions = {
|
|
86923
|
-
deploymentId: resumeContext.deploymentId,
|
|
86924
|
-
specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY2
|
|
86925
|
-
};
|
|
86926
|
-
const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION2 || world.capabilities?.hookResumeDedup === true;
|
|
86927
|
-
const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
|
|
86928
|
-
span?.setAttributes({
|
|
86929
|
-
"workflow.hook.resume_strategy": "sequential"
|
|
86930
|
-
});
|
|
86931
|
-
const resumeId = canClaimResume ? generateResumeId2() : void 0;
|
|
86932
|
-
const payloadDigest = canClaimResume ? await computeResumePayloadDigest2(dehydratedPayload) : void 0;
|
|
86933
|
-
if (resumeId) {
|
|
86934
|
-
span?.setAttributes({ "workflow.hook.resume_id": resumeId });
|
|
86935
|
-
}
|
|
86936
|
-
const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError2.is(err) || RunExpiredError2.is(err), "isHookGoneError");
|
|
87280
|
+
}, "assertResendable");
|
|
87281
|
+
for (; ; ) {
|
|
86937
87282
|
try {
|
|
86938
|
-
await world
|
|
86939
|
-
eventType: "hook_received",
|
|
86940
|
-
specVersion: SPEC_VERSION_CURRENT2,
|
|
86941
|
-
correlationId: hook.hookId,
|
|
86942
|
-
eventData: {
|
|
86943
|
-
...v1Compat ? {} : { token: hook.token },
|
|
86944
|
-
payload: dehydratedPayload
|
|
86945
|
-
}
|
|
86946
|
-
}, {
|
|
86947
|
-
v1Compat,
|
|
86948
|
-
...resumeId && payloadDigest ? { resumeId, resumePayloadDigest: payloadDigest } : {}
|
|
86949
|
-
});
|
|
87283
|
+
return await resumeHookAttempt2(world, span, target2, payload, keyOverride, fresh, resumeRequestedAtMs, resumeId, webhookOnly);
|
|
86950
87284
|
} catch (err) {
|
|
86951
|
-
if (
|
|
86952
|
-
throw
|
|
87285
|
+
if (err !== null && typeof err === "object" && notFoundReasons2.get(err) === "not-webhook") {
|
|
87286
|
+
throw err;
|
|
87287
|
+
}
|
|
87288
|
+
if (redirects >= MAX_FORCE_CLAIM_REDIRECTS2) {
|
|
87289
|
+
if (HookForceClaimedError2.is(err)) {
|
|
87290
|
+
span?.setAttributes({
|
|
87291
|
+
"workflow.hook.resume_redirects_exhausted": true
|
|
87292
|
+
});
|
|
87293
|
+
throw new WorkflowRuntimeError2(`Hook token "${token}" changed owner ${redirects} times while this resume was in flight; nothing was delivered \u2014 retry the resume`, { cause: err });
|
|
87294
|
+
}
|
|
87295
|
+
throw err;
|
|
87296
|
+
}
|
|
87297
|
+
if (HookForceClaimedError2.is(err)) {
|
|
87298
|
+
assertResendable(err);
|
|
87299
|
+
redirects++;
|
|
87300
|
+
span?.setAttributes({
|
|
87301
|
+
"workflow.hook.resume_redirects": redirects,
|
|
87302
|
+
"workflow.hook.resume_redirect_to_run": err.claimedByRunId
|
|
87303
|
+
});
|
|
87304
|
+
target2 = token;
|
|
87305
|
+
fresh = true;
|
|
87306
|
+
keyOverride = void 0;
|
|
87307
|
+
lookupsAfterRedirect = 0;
|
|
87308
|
+
continue;
|
|
87309
|
+
}
|
|
87310
|
+
if (HookNotFoundError2.is(err) && redirects > 0 && typeof target2 === "string" && lookupsAfterRedirect < MAX_LOOKUPS_AFTER_REDIRECT) {
|
|
87311
|
+
assertResendable(err);
|
|
87312
|
+
lookupsAfterRedirect++;
|
|
87313
|
+
await new Promise((resolve3) => setTimeout(resolve3, 50));
|
|
87314
|
+
continue;
|
|
87315
|
+
}
|
|
87316
|
+
if (HookNotFoundError2.is(err) && notFoundReasons2.get(err) !== "lookup") {
|
|
87317
|
+
const attemptedHookId = typeof target2 === "string" ? void 0 : target2.hookId;
|
|
87318
|
+
let relocated;
|
|
87319
|
+
try {
|
|
87320
|
+
relocated = await world.hooks.getByToken(token);
|
|
87321
|
+
} catch (lookupError) {
|
|
87322
|
+
if (!HookNotFoundError2.is(lookupError)) {
|
|
87323
|
+
runtimeLogger2.warn("Hook resume: re-resolving the token after a not-found failed; surfacing the original error", {
|
|
87324
|
+
token,
|
|
87325
|
+
error: lookupError instanceof Error ? lookupError.message : String(lookupError)
|
|
87326
|
+
});
|
|
87327
|
+
}
|
|
87328
|
+
}
|
|
87329
|
+
if (relocated?.claimedFrom !== void 0 && relocated.hookId !== attemptedHookId && (attemptedHookId === void 0 || relocated.claimedFrom.hookId === attemptedHookId) && !(webhookOnly && relocated.isWebhook === false)) {
|
|
87330
|
+
assertResendable(err);
|
|
87331
|
+
redirects++;
|
|
87332
|
+
span?.setAttributes({
|
|
87333
|
+
"workflow.hook.resume_redirects": redirects,
|
|
87334
|
+
"workflow.hook.resume_redirect_to_run": relocated.runId
|
|
87335
|
+
});
|
|
87336
|
+
target2 = relocated;
|
|
87337
|
+
fresh = true;
|
|
87338
|
+
keyOverride = void 0;
|
|
87339
|
+
continue;
|
|
87340
|
+
}
|
|
86953
87341
|
}
|
|
86954
87342
|
throw err;
|
|
86955
87343
|
}
|
|
86956
|
-
span?.setAttributes(HookResumeCommitted2(true));
|
|
86957
|
-
const queuePublishRequestedAtMs = Date.now();
|
|
86958
|
-
await publishHookWakeWithRetry2(() => world.queue(queueName, {
|
|
86959
|
-
runId: hook.runId,
|
|
86960
|
-
traceCarrier: resumeContext.traceCarrier ?? void 0,
|
|
86961
|
-
hookResumeTiming: {
|
|
86962
|
-
resumeRequestedAtMs,
|
|
86963
|
-
queuePublishRequestedAtMs,
|
|
86964
|
-
strategy: "sequential"
|
|
86965
|
-
}
|
|
86966
|
-
}, {
|
|
86967
|
-
...queueOptions,
|
|
86968
|
-
// Dedup retried publishes whose response was lost: a
|
|
86969
|
-
// duplicate wake is harmless for correctness (deterministic
|
|
86970
|
-
// replay) but costs a full replay of the run, and the queue
|
|
86971
|
-
// accepts a repeated idempotency key by delivering only one
|
|
86972
|
-
// of the messages. Claim-less writes have no resumeId and
|
|
86973
|
-
// keep the previous behavior.
|
|
86974
|
-
...resumeId ? { idempotencyKey: `hook-${resumeId}` } : {}
|
|
86975
|
-
}), world.isDeploymentUnavailableError?.bind(world));
|
|
86976
|
-
span?.setAttributes(HookWakePublished2(true));
|
|
86977
|
-
return asLazyMetadataHook2(hook);
|
|
86978
|
-
} catch (err) {
|
|
86979
|
-
span?.setAttributes({
|
|
86980
|
-
...HookToken2(typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token),
|
|
86981
|
-
...HookFound2(false)
|
|
86982
|
-
});
|
|
86983
|
-
throw err;
|
|
86984
87344
|
}
|
|
86985
87345
|
});
|
|
86986
87346
|
});
|
|
86987
87347
|
}
|
|
87348
|
+
async function resumeHookAttempt2(world, span, tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, logicalResumeId, webhookOnly) {
|
|
87349
|
+
try {
|
|
87350
|
+
const suppliedToken = typeof tokenOrHook === "string";
|
|
87351
|
+
let hook;
|
|
87352
|
+
if (suppliedToken) {
|
|
87353
|
+
try {
|
|
87354
|
+
hook = await world.hooks.getByToken(tokenOrHook);
|
|
87355
|
+
} catch (lookupError) {
|
|
87356
|
+
if (HookNotFoundError2.is(lookupError)) {
|
|
87357
|
+
notFoundReasons2.set(lookupError, "lookup");
|
|
87358
|
+
}
|
|
87359
|
+
throw lookupError;
|
|
87360
|
+
}
|
|
87361
|
+
} else {
|
|
87362
|
+
hook = tokenOrHook;
|
|
87363
|
+
}
|
|
87364
|
+
if (webhookOnly && hook.isWebhook === false) {
|
|
87365
|
+
const notWebhook = new HookNotFoundError2(hook.token);
|
|
87366
|
+
notFoundReasons2.set(notWebhook, "not-webhook");
|
|
87367
|
+
throw notWebhook;
|
|
87368
|
+
}
|
|
87369
|
+
const hookResumeCapabilitiesAreFresh = suppliedToken || hookFreshlyLookedUp;
|
|
87370
|
+
const info = await resolveHookResumeInfo2(hook);
|
|
87371
|
+
const { resumeContext } = info;
|
|
87372
|
+
span?.setAttributes({
|
|
87373
|
+
...HookToken2(hook.token),
|
|
87374
|
+
...HookId2(hook.hookId),
|
|
87375
|
+
...WorkflowRunId4(hook.runId),
|
|
87376
|
+
"workflow.hook.resume_context_source": info.source
|
|
87377
|
+
});
|
|
87378
|
+
if (info.run && isTerminalWorkflowRunStatus2(info.run.status)) {
|
|
87379
|
+
throw new HookNotFoundError2(hook.token);
|
|
87380
|
+
}
|
|
87381
|
+
const capabilities = getRunCapabilities2(resumeContext.workflowCoreVersion);
|
|
87382
|
+
let payloadKey;
|
|
87383
|
+
const runPublicKey = encryptionKeyOverride ? (
|
|
87384
|
+
// The caller already holds a key (resumeWebhook resolved one to
|
|
87385
|
+
// hydrate hook metadata), so sealing would add an ECDH for no
|
|
87386
|
+
// saved round trip. Reuse what it resolved.
|
|
87387
|
+
void 0
|
|
87388
|
+
) : decodeRunPublicKey2(resumeContext.encryptionPublicKey);
|
|
87389
|
+
if (runPublicKey) {
|
|
87390
|
+
payloadKey = sealTo2(runPublicKey);
|
|
87391
|
+
} else {
|
|
87392
|
+
let encryptionKey = encryptionKeyOverride ?? await resolveHookEncryptionKey2(hook, info);
|
|
87393
|
+
if (!capabilities.supportedFormats.has(SerializationFormat2.ENCRYPTED)) {
|
|
87394
|
+
encryptionKey = void 0;
|
|
87395
|
+
}
|
|
87396
|
+
payloadKey = encryptionKey;
|
|
87397
|
+
}
|
|
87398
|
+
const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION2 && capabilities.supportedFormats.has(SerializationFormat2.GZIP);
|
|
87399
|
+
const ops = [];
|
|
87400
|
+
const readbackOps = [];
|
|
87401
|
+
const v1Compat = isLegacySpecVersion2(hook.specVersion);
|
|
87402
|
+
const dehydratedPayload = await dehydrateStepReturnValue2(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
|
|
87403
|
+
await Promise.all(ops.map((op) => op.catch((error121) => {
|
|
87404
|
+
if (error121 !== void 0)
|
|
87405
|
+
throw error121;
|
|
87406
|
+
})));
|
|
87407
|
+
safeWaitUntil2(Promise.all(readbackOps), (err) => {
|
|
87408
|
+
if (err === void 0)
|
|
87409
|
+
return;
|
|
87410
|
+
runtimeLogger2.warn("Background readback of hook payload failed", {
|
|
87411
|
+
workflowRunId: hook.runId,
|
|
87412
|
+
hookId: hook.hookId,
|
|
87413
|
+
error: err instanceof Error ? err.message : String(err)
|
|
87414
|
+
});
|
|
87415
|
+
});
|
|
87416
|
+
if (world.capabilities?.invoke === true && !v1Compat && dehydratedPayload instanceof Uint8Array) {
|
|
87417
|
+
if (!world.invoke) {
|
|
87418
|
+
throw new WorkflowRuntimeError2("World advertises invoke without implementing it");
|
|
87419
|
+
}
|
|
87420
|
+
span?.setAttributes({ "workflow.hook.resume_strategy": "invoke" });
|
|
87421
|
+
const result2 = HookInvocationResultSchema2.parse(await world.invoke(hook.runId, {
|
|
87422
|
+
type: "hook_resume",
|
|
87423
|
+
version: 1,
|
|
87424
|
+
hookId: hook.hookId,
|
|
87425
|
+
token: hook.token,
|
|
87426
|
+
payload: dehydratedPayload
|
|
87427
|
+
}, { idempotencyKey: logicalResumeId }));
|
|
87428
|
+
if (result2.status === "rejected") {
|
|
87429
|
+
if (result2.code === "HOOK_NOT_FOUND")
|
|
87430
|
+
throw new HookNotFoundError2(hook.token);
|
|
87431
|
+
throw new WorkflowRuntimeError2("Executor rejected the hook invocation input");
|
|
87432
|
+
}
|
|
87433
|
+
span?.setAttributes(HookResumeCommitted2(true));
|
|
87434
|
+
return asLazyMetadataHook2(hook);
|
|
87435
|
+
}
|
|
87436
|
+
span?.setAttributes({
|
|
87437
|
+
...WorkflowName2(resumeContext.workflowName)
|
|
87438
|
+
});
|
|
87439
|
+
const originLink = await linkToTraceCarrier2(resumeContext.traceCarrier);
|
|
87440
|
+
if (originLink) {
|
|
87441
|
+
span?.addLink?.(originLink);
|
|
87442
|
+
}
|
|
87443
|
+
const queueName = getWorkflowQueueName2(resumeContext.workflowName);
|
|
87444
|
+
const queueOptions = {
|
|
87445
|
+
deploymentId: resumeContext.deploymentId,
|
|
87446
|
+
specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY2
|
|
87447
|
+
};
|
|
87448
|
+
const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION2 || world.capabilities?.hookResumeDedup === true;
|
|
87449
|
+
const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
|
|
87450
|
+
span?.setAttributes({
|
|
87451
|
+
"workflow.hook.resume_strategy": "sequential"
|
|
87452
|
+
});
|
|
87453
|
+
const resumeId = canClaimResume ? logicalResumeId : void 0;
|
|
87454
|
+
const payloadDigest = canClaimResume ? await computeResumePayloadDigest2(dehydratedPayload) : void 0;
|
|
87455
|
+
if (resumeId) {
|
|
87456
|
+
span?.setAttributes({ "workflow.hook.resume_id": resumeId });
|
|
87457
|
+
}
|
|
87458
|
+
const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError2.is(err) || RunExpiredError2.is(err), "isHookGoneError");
|
|
87459
|
+
try {
|
|
87460
|
+
await world.events.create(hook.runId, {
|
|
87461
|
+
eventType: "hook_received",
|
|
87462
|
+
specVersion: SPEC_VERSION_CURRENT2,
|
|
87463
|
+
correlationId: hook.hookId,
|
|
87464
|
+
eventData: {
|
|
87465
|
+
...v1Compat ? {} : { token: hook.token },
|
|
87466
|
+
payload: dehydratedPayload
|
|
87467
|
+
}
|
|
87468
|
+
}, {
|
|
87469
|
+
v1Compat,
|
|
87470
|
+
...resumeId && payloadDigest ? { resumeId, resumePayloadDigest: payloadDigest } : {}
|
|
87471
|
+
});
|
|
87472
|
+
} catch (err) {
|
|
87473
|
+
if (HookForceClaimedError2.is(err))
|
|
87474
|
+
throw err;
|
|
87475
|
+
if (isHookGoneError(err)) {
|
|
87476
|
+
throw new HookNotFoundError2(hook.token);
|
|
87477
|
+
}
|
|
87478
|
+
throw err;
|
|
87479
|
+
}
|
|
87480
|
+
span?.setAttributes(HookResumeCommitted2(true));
|
|
87481
|
+
const queuePublishRequestedAtMs = Date.now();
|
|
87482
|
+
await publishHookWakeWithRetry2(() => world.queue(queueName, {
|
|
87483
|
+
runId: hook.runId,
|
|
87484
|
+
traceCarrier: resumeContext.traceCarrier ?? void 0,
|
|
87485
|
+
hookResumeTiming: {
|
|
87486
|
+
resumeRequestedAtMs,
|
|
87487
|
+
queuePublishRequestedAtMs,
|
|
87488
|
+
strategy: "sequential"
|
|
87489
|
+
}
|
|
87490
|
+
}, {
|
|
87491
|
+
...queueOptions,
|
|
87492
|
+
// Dedup retried publishes whose response was lost: a
|
|
87493
|
+
// duplicate wake is harmless for correctness (deterministic
|
|
87494
|
+
// replay) but costs a full replay of the run, and the queue
|
|
87495
|
+
// accepts a repeated idempotency key by delivering only one
|
|
87496
|
+
// of the messages. Claim-less writes have no resumeId and
|
|
87497
|
+
// keep the previous behavior.
|
|
87498
|
+
...resumeId ? { idempotencyKey: `hook-${resumeId}` } : {}
|
|
87499
|
+
}), world.isDeploymentUnavailableError?.bind(world));
|
|
87500
|
+
span?.setAttributes(HookWakePublished2(true));
|
|
87501
|
+
return asLazyMetadataHook2(hook);
|
|
87502
|
+
} catch (err) {
|
|
87503
|
+
span?.setAttributes({
|
|
87504
|
+
...HookToken2(typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token),
|
|
87505
|
+
...HookFound2(false)
|
|
87506
|
+
});
|
|
87507
|
+
throw err;
|
|
87508
|
+
}
|
|
87509
|
+
}
|
|
86988
87510
|
async function resumeWebhook2(token, request) {
|
|
86989
87511
|
const resumeRequestedAtMs = Date.now();
|
|
86990
87512
|
const world = await getWorldLazy2();
|
|
@@ -87008,7 +87530,7 @@ async function resumeWebhook2(token, request) {
|
|
|
87008
87530
|
} else {
|
|
87009
87531
|
response = new Response(null, { status: 202 });
|
|
87010
87532
|
}
|
|
87011
|
-
await resumeHookImpl2(hook, request, metadataEncryptionKey(), true, resumeRequestedAtMs);
|
|
87533
|
+
await resumeHookImpl2(hook, request, metadataEncryptionKey(), true, resumeRequestedAtMs, true);
|
|
87012
87534
|
if (responseReadable) {
|
|
87013
87535
|
const reader = responseReadable.getReader();
|
|
87014
87536
|
const chunk = await reader.read();
|
|
@@ -87024,7 +87546,7 @@ async function resumeWebhook2(token, request) {
|
|
|
87024
87546
|
}
|
|
87025
87547
|
return response;
|
|
87026
87548
|
}
|
|
87027
|
-
var generateResumeId2,
|
|
87549
|
+
var generateResumeId2, MAX_FORCE_CLAIM_REDIRECTS2, notFoundReasons2;
|
|
87028
87550
|
var init_resume_hook2 = __esm({
|
|
87029
87551
|
"../core/dist/runtime/resume-hook.js"() {
|
|
87030
87552
|
"use strict";
|
|
@@ -87042,13 +87564,11 @@ var init_resume_hook2 = __esm({
|
|
|
87042
87564
|
init_telemetry4();
|
|
87043
87565
|
init_get_world_lazy2();
|
|
87044
87566
|
init_helpers3();
|
|
87567
|
+
init_hook_wake2();
|
|
87045
87568
|
init_invocations2();
|
|
87046
87569
|
init_wait_until2();
|
|
87047
87570
|
generateResumeId2 = monotonicFactory2();
|
|
87048
87571
|
__name(computeResumePayloadDigest2, "computeResumePayloadDigest");
|
|
87049
|
-
HOOK_WAKE_RETRY_DELAYS_MS2 = [25, 100];
|
|
87050
|
-
__name(isRetryableWakeError2, "isRetryableWakeError");
|
|
87051
|
-
__name(publishHookWakeWithRetry2, "publishHookWakeWithRetry");
|
|
87052
87572
|
__name(resumeContextFromRun2, "resumeContextFromRun");
|
|
87053
87573
|
__name(resolveHookResumeInfo2, "resolveHookResumeInfo");
|
|
87054
87574
|
__name(resolveHookEncryptionKey2, "resolveHookEncryptionKey");
|
|
@@ -87057,7 +87577,10 @@ var init_resume_hook2 = __esm({
|
|
|
87057
87577
|
__name(asLazyMetadataHook2, "asLazyMetadataHook");
|
|
87058
87578
|
__name(getHookByToken3, "getHookByToken");
|
|
87059
87579
|
__name(resumeHook2, "resumeHook");
|
|
87580
|
+
MAX_FORCE_CLAIM_REDIRECTS2 = 3;
|
|
87581
|
+
notFoundReasons2 = /* @__PURE__ */ new WeakMap();
|
|
87060
87582
|
__name(resumeHookImpl2, "resumeHookImpl");
|
|
87583
|
+
__name(resumeHookAttempt2, "resumeHookAttempt");
|
|
87061
87584
|
__name(resumeWebhook2, "resumeWebhook");
|
|
87062
87585
|
}
|
|
87063
87586
|
});
|
|
@@ -89341,6 +89864,11 @@ function getInlineOwnershipLeaseSeconds() {
|
|
|
89341
89864
|
function getReplayDivergenceMaxRetries() {
|
|
89342
89865
|
return envNumber2("WORKFLOW_REPLAY_DIVERGENCE_MAX_RETRIES", REPLAY_DIVERGENCE_MAX_RETRIES, { integer: true });
|
|
89343
89866
|
}
|
|
89867
|
+
function getOpenWaitClockSkewMs() {
|
|
89868
|
+
return envNumber2("WORKFLOW_OPEN_WAIT_CLOCK_SKEW_MS", OPEN_WAIT_CLOCK_SKEW_MS, {
|
|
89869
|
+
integer: true
|
|
89870
|
+
});
|
|
89871
|
+
}
|
|
89344
89872
|
function getPreconditionMaxInProcessRestarts() {
|
|
89345
89873
|
return envNumber2("WORKFLOW_PRECONDITION_MAX_INPROCESS_RESTARTS", PRECONDITION_MAX_INPROCESS_RESTARTS, { integer: true });
|
|
89346
89874
|
}
|
|
@@ -89353,7 +89881,7 @@ function getPreconditionReinvokeDelaySeconds() {
|
|
|
89353
89881
|
function getDeploymentMismatchMaxRetries() {
|
|
89354
89882
|
return envNumber2("WORKFLOW_DEPLOYMENT_MISMATCH_MAX_RETRIES", DEPLOYMENT_MISMATCH_MAX_RETRIES, { integer: true, min: 0 });
|
|
89355
89883
|
}
|
|
89356
|
-
var MAX_QUEUE_DELIVERIES, REPLAY_TIMEOUT_MS, MIN_REPLAY_TIMEOUT_MS, MAX_REPLAY_TIMEOUT_MS, warned, REPLAY_TIMEOUT_MAX_RETRIES, MAX_INLINE_STEPS, MIN_MAX_INLINE_STEPS, MAX_MAX_INLINE_STEPS, MAX_RESILIENT_STEP_INPUT_BYTES, MAX_BATCH_FANOUT_EVENTS, INLINE_OWNERSHIP_LEASE_SECONDS, MAX_INLINE_OWNERSHIP_LEASE_SECONDS, REPLAY_DIVERGENCE_MAX_RETRIES, PRECONDITION_MAX_INPROCESS_RESTARTS, PRECONDITION_MAX_REINVOCATIONS, PRECONDITION_REINVOKE_DELAY_SECONDS, DEPLOYMENT_MISMATCH_MAX_RETRIES;
|
|
89884
|
+
var MAX_QUEUE_DELIVERIES, REPLAY_TIMEOUT_MS, MIN_REPLAY_TIMEOUT_MS, MAX_REPLAY_TIMEOUT_MS, warned, REPLAY_TIMEOUT_MAX_RETRIES, MAX_INLINE_STEPS, MIN_MAX_INLINE_STEPS, MAX_MAX_INLINE_STEPS, MAX_RESILIENT_STEP_INPUT_BYTES, MAX_BATCH_FANOUT_EVENTS, INLINE_OWNERSHIP_LEASE_SECONDS, MAX_INLINE_OWNERSHIP_LEASE_SECONDS, REPLAY_DIVERGENCE_MAX_RETRIES, OPEN_WAIT_CLOCK_SKEW_MS, PRECONDITION_MAX_INPROCESS_RESTARTS, PRECONDITION_MAX_REINVOCATIONS, PRECONDITION_REINVOKE_DELAY_SECONDS, DEPLOYMENT_MISMATCH_MAX_RETRIES;
|
|
89357
89885
|
var init_constants3 = __esm({
|
|
89358
89886
|
"../core/dist/runtime/constants.js"() {
|
|
89359
89887
|
"use strict";
|
|
@@ -89394,6 +89922,8 @@ var init_constants3 = __esm({
|
|
|
89394
89922
|
__name(getInlineOwnershipLeaseSeconds, "getInlineOwnershipLeaseSeconds");
|
|
89395
89923
|
REPLAY_DIVERGENCE_MAX_RETRIES = 3;
|
|
89396
89924
|
__name(getReplayDivergenceMaxRetries, "getReplayDivergenceMaxRetries");
|
|
89925
|
+
OPEN_WAIT_CLOCK_SKEW_MS = 3e4;
|
|
89926
|
+
__name(getOpenWaitClockSkewMs, "getOpenWaitClockSkewMs");
|
|
89397
89927
|
PRECONDITION_MAX_INPROCESS_RESTARTS = 3;
|
|
89398
89928
|
__name(getPreconditionMaxInProcessRestarts, "getPreconditionMaxInProcessRestarts");
|
|
89399
89929
|
PRECONDITION_MAX_REINVOCATIONS = 5;
|
|
@@ -91438,11 +91968,11 @@ var init_step_executor = __esm({
|
|
|
91438
91968
|
});
|
|
91439
91969
|
|
|
91440
91970
|
// ../core/dist/runtime/step-single-flight.js
|
|
91441
|
-
async function runStepSingleFlight(runId, correlationId, execute) {
|
|
91971
|
+
async function runStepSingleFlight(runId, correlationId, execute, logLevel = "warn") {
|
|
91442
91972
|
const key = `${runId}:${correlationId}`;
|
|
91443
91973
|
const existing = singleFlight.inFlight.get(key);
|
|
91444
91974
|
if (existing) {
|
|
91445
|
-
runtimeLogger2
|
|
91975
|
+
runtimeLogger2[logLevel]("Step execution already in flight in this process; awaiting its settlement instead of executing again", { workflowRunId: runId, stepId: correlationId });
|
|
91446
91976
|
try {
|
|
91447
91977
|
await existing;
|
|
91448
91978
|
} catch {
|
|
@@ -96634,6 +97164,28 @@ function createQuickJSSerde(vm, capturedRoot) {
|
|
|
96634
97164
|
reduced.cause = shape.cause;
|
|
96635
97165
|
return reduced;
|
|
96636
97166
|
}, "HookConflictError"),
|
|
97167
|
+
HookForceClaimedError: /* @__PURE__ */ __name((value) => {
|
|
97168
|
+
if (!isHandle(value) || !value.isError)
|
|
97169
|
+
return false;
|
|
97170
|
+
if (chainedString(value, "name") !== "HookForceClaimedError")
|
|
97171
|
+
return false;
|
|
97172
|
+
const shape = reduceErrorShape(value);
|
|
97173
|
+
const reduced = {
|
|
97174
|
+
message: shape.message,
|
|
97175
|
+
stack: shape.stack,
|
|
97176
|
+
token: own3(value, "token"),
|
|
97177
|
+
claimedByRunId: own3(value, "claimedByRunId")
|
|
97178
|
+
};
|
|
97179
|
+
const claimedByHookId = own3(value, "claimedByHookId");
|
|
97180
|
+
if (claimedByHookId && !claimedByHookId.isUndefined) {
|
|
97181
|
+
reduced.claimedByHookId = claimedByHookId;
|
|
97182
|
+
} else {
|
|
97183
|
+
claimedByHookId?.dispose();
|
|
97184
|
+
}
|
|
97185
|
+
if (Object.hasOwn(shape, "cause"))
|
|
97186
|
+
reduced.cause = shape.cause;
|
|
97187
|
+
return reduced;
|
|
97188
|
+
}, "HookForceClaimedError"),
|
|
96637
97189
|
RangeError: namedErrorSubclassReducer("RangeError"),
|
|
96638
97190
|
ReferenceError: namedErrorSubclassReducer("ReferenceError"),
|
|
96639
97191
|
RetryableError: /* @__PURE__ */ __name((value) => {
|
|
@@ -97221,6 +97773,42 @@ function createQuickJSSerde(vm, capturedRoot) {
|
|
|
97221
97773
|
}
|
|
97222
97774
|
return error121;
|
|
97223
97775
|
}, "HookConflictError"),
|
|
97776
|
+
HookForceClaimedError: /* @__PURE__ */ __name((value) => {
|
|
97777
|
+
const cls = registeredErrorClass("@workflow/errors//HookForceClaimedError");
|
|
97778
|
+
let error121;
|
|
97779
|
+
if (cls) {
|
|
97780
|
+
const token = own3(value, "token") ?? vm.undefined;
|
|
97781
|
+
const claimedByRunId = own3(value, "claimedByRunId") ?? vm.undefined;
|
|
97782
|
+
const claimedByHookId = own3(value, "claimedByHookId") ?? vm.undefined;
|
|
97783
|
+
error121 = vm.construct(cls, token, claimedByRunId, claimedByHookId);
|
|
97784
|
+
if (token !== vm.undefined)
|
|
97785
|
+
token.dispose();
|
|
97786
|
+
if (claimedByRunId !== vm.undefined)
|
|
97787
|
+
claimedByRunId.dispose();
|
|
97788
|
+
if (claimedByHookId !== vm.undefined)
|
|
97789
|
+
claimedByHookId.dispose();
|
|
97790
|
+
const stack = own3(value, "stack");
|
|
97791
|
+
if (stack && !stack.isUndefined)
|
|
97792
|
+
define2(error121, "stack", stack);
|
|
97793
|
+
stack?.dispose();
|
|
97794
|
+
if (guestHasOwn(value, "cause")) {
|
|
97795
|
+
const cause = own3(value, "cause") ?? vm.undefined;
|
|
97796
|
+
define2(error121, "cause", cause);
|
|
97797
|
+
if (cause !== vm.undefined)
|
|
97798
|
+
cause.dispose();
|
|
97799
|
+
}
|
|
97800
|
+
cls.dispose();
|
|
97801
|
+
} else {
|
|
97802
|
+
error121 = buildError(i.Error, value, { name: "HookForceClaimedError" });
|
|
97803
|
+
for (const field of ["token", "claimedByRunId", "claimedByHookId"]) {
|
|
97804
|
+
const handle = own3(value, field);
|
|
97805
|
+
if (handle && !handle.isUndefined)
|
|
97806
|
+
define2(error121, field, handle);
|
|
97807
|
+
handle?.dispose();
|
|
97808
|
+
}
|
|
97809
|
+
}
|
|
97810
|
+
return error121;
|
|
97811
|
+
}, "HookForceClaimedError"),
|
|
97224
97812
|
RangeError: namedErrorSubclassReviver("RangeError"),
|
|
97225
97813
|
ReferenceError: namedErrorSubclassReviver("ReferenceError"),
|
|
97226
97814
|
RetryableError: /* @__PURE__ */ __name((value) => {
|
|
@@ -97818,6 +98406,7 @@ var init_quickjs_serde = __esm({
|
|
|
97818
98406
|
"workflow-class-registry",
|
|
97819
98407
|
"@workflow/errors//FatalError",
|
|
97820
98408
|
"@workflow/errors//HookConflictError",
|
|
98409
|
+
"@workflow/errors//HookForceClaimedError",
|
|
97821
98410
|
"@workflow/errors//RetryableError",
|
|
97822
98411
|
"@workflow/errors//RuntimeDecryptionError",
|
|
97823
98412
|
"@workflow/errors//StreamError"
|
|
@@ -98509,13 +99098,30 @@ async function processEvents(vm, serde, events, advanceClock, encryptionKey) {
|
|
|
98509
99098
|
case "hook_conflict": {
|
|
98510
99099
|
const conflictToken = eventData?.token ?? "unknown";
|
|
98511
99100
|
const conflictingRunId = eventData?.conflictingRunId;
|
|
99101
|
+
const forceRefusedReason = eventData?.forceRefusedReason;
|
|
98512
99102
|
const didSettle = vm.dump(vm.evalCode(`(function(){
|
|
98513
99103
|
var cid = ${JSON.stringify(cid)};
|
|
98514
99104
|
var token = ${JSON.stringify(conflictToken)};
|
|
98515
99105
|
var conflictingRunId = ${JSON.stringify(conflictingRunId ?? null)};
|
|
99106
|
+
var forceRefused = ${JSON.stringify(forceRefusedReason !== void 0)};
|
|
98516
99107
|
var ErrCls = globalThis[Symbol.for('@workflow/errors//HookConflictError')];
|
|
98517
99108
|
var err;
|
|
98518
|
-
|
|
99109
|
+
var hookState = globalThis.__hooks && globalThis.__hooks[cid];
|
|
99110
|
+
// A forced hook asked for a guarantee the World could not give
|
|
99111
|
+
// (older server, kill switch): a misconfiguration, not the
|
|
99112
|
+
// ordinary conflict the caller opted out of. Mirrors hook.ts.
|
|
99113
|
+
var forced = !!(hookState && hookState.force) && !forceRefused;
|
|
99114
|
+
if (forced) {
|
|
99115
|
+
var FatalCls = globalThis[Symbol.for('@workflow/errors//FatalError')];
|
|
99116
|
+
var forcedMessage = 'createHook({ experimental_force: true }) for token "' + token + '" was answered with a hook_conflict: the configured World does not support force-claiming hook tokens' + (conflictingRunId ? ' (run "' + conflictingRunId + '" holds it)' : '') + '.';
|
|
99117
|
+
if (typeof FatalCls === 'function') {
|
|
99118
|
+
err = new FatalCls(forcedMessage);
|
|
99119
|
+
} else {
|
|
99120
|
+
err = new Error(forcedMessage);
|
|
99121
|
+
err.name = 'FatalError';
|
|
99122
|
+
err.fatal = true;
|
|
99123
|
+
}
|
|
99124
|
+
} else if (typeof ErrCls === 'function') {
|
|
98519
99125
|
err = new ErrCls(token, conflictingRunId || undefined);
|
|
98520
99126
|
} else {
|
|
98521
99127
|
err = new Error('Hook token "' + token + '" is already in use by another workflow');
|
|
@@ -98524,7 +99130,7 @@ async function processEvents(vm, serde, events, advanceClock, encryptionKey) {
|
|
|
98524
99130
|
if (conflictingRunId) err.conflictingRunId = conflictingRunId;
|
|
98525
99131
|
}
|
|
98526
99132
|
var run = null;
|
|
98527
|
-
if (conflictingRunId) {
|
|
99133
|
+
if (conflictingRunId && !forced) {
|
|
98528
99134
|
var reg = globalThis[Symbol.for('workflow-class-registry')];
|
|
98529
99135
|
var RunCls = reg && reg.get('class//workflow//Run');
|
|
98530
99136
|
var des = RunCls && RunCls[Symbol.for('workflow-deserialize')];
|
|
@@ -98588,6 +99194,48 @@ async function processEvents(vm, serde, events, advanceClock, encryptionKey) {
|
|
|
98588
99194
|
break;
|
|
98589
99195
|
}
|
|
98590
99196
|
case "hook_disposed": {
|
|
99197
|
+
const claimedBy = eventData?.forceClaimedBy;
|
|
99198
|
+
if (claimedBy && typeof claimedBy.runId === "string") {
|
|
99199
|
+
const hookState = vm.dump(vm.evalCode(`(function(){
|
|
99200
|
+
var cid = ${JSON.stringify(cid)};
|
|
99201
|
+
var state = globalThis.__hooks && globalThis.__hooks[cid];
|
|
99202
|
+
var token = state ? state.token : ${JSON.stringify(eventData?.token ?? "")};
|
|
99203
|
+
var claimedByRunId = ${JSON.stringify(claimedBy.runId)};
|
|
99204
|
+
var claimedByHookId = ${JSON.stringify(claimedBy.hookId ?? null)};
|
|
99205
|
+
var ErrCls = globalThis[Symbol.for('@workflow/errors//HookForceClaimedError')];
|
|
99206
|
+
var err;
|
|
99207
|
+
if (typeof ErrCls === 'function') {
|
|
99208
|
+
err = new ErrCls(token, claimedByRunId, claimedByHookId || undefined);
|
|
99209
|
+
} else {
|
|
99210
|
+
err = new Error('Hook token "' + token + '" was force-claimed by another workflow (run "' + claimedByRunId + '")');
|
|
99211
|
+
err.name = 'HookForceClaimedError';
|
|
99212
|
+
err.token = token;
|
|
99213
|
+
err.claimedByRunId = claimedByRunId;
|
|
99214
|
+
if (claimedByHookId) err.claimedByHookId = claimedByHookId;
|
|
99215
|
+
}
|
|
99216
|
+
var settled = false;
|
|
99217
|
+
if (state) {
|
|
99218
|
+
state.forceClaimed = err;
|
|
99219
|
+
var gc = state.getConflictResolvers;
|
|
99220
|
+
state.getConflictResolvers = [];
|
|
99221
|
+
for (var i = 0; i < gc.length; i++) { gc[i].resolve(null); settled = true; }
|
|
99222
|
+
}
|
|
99223
|
+
if (globalThis.__resolvers[cid]) {
|
|
99224
|
+
globalThis.__resolvers[cid].reject(err);
|
|
99225
|
+
delete globalThis.__resolvers[cid];
|
|
99226
|
+
settled = true;
|
|
99227
|
+
}
|
|
99228
|
+
return settled;
|
|
99229
|
+
})()`));
|
|
99230
|
+
if (hookState) {
|
|
99231
|
+
resolved = true;
|
|
99232
|
+
let b;
|
|
99233
|
+
do {
|
|
99234
|
+
b = vm.executePendingJobs();
|
|
99235
|
+
} while (b > 0);
|
|
99236
|
+
}
|
|
99237
|
+
markCreated(vm, cidJs);
|
|
99238
|
+
}
|
|
98591
99239
|
markCreated(vm, cidJs, "hook_dispose");
|
|
98592
99240
|
break;
|
|
98593
99241
|
}
|
|
@@ -99346,6 +99994,20 @@ globalThis[Symbol.for("WORKFLOW_CREATE_HOOK")] = function(options) {
|
|
|
99346
99994
|
unsupportedRetentionError.fatal = true;
|
|
99347
99995
|
throw unsupportedRetentionError;
|
|
99348
99996
|
}
|
|
99997
|
+
if (options.experimental_force === true) {
|
|
99998
|
+
if (options.token === undefined || options.token === null) {
|
|
99999
|
+
throw new Error('\`createHook()\` was called with \`experimental_force: true\` but no \`token\`. Force-claiming only applies to an explicit token another run may hold.');
|
|
100000
|
+
}
|
|
100001
|
+
if (options.isWebhook === true) {
|
|
100002
|
+
throw new Error('Webhook hooks do not support \`experimental_force\`. Use a non-webhook \`createHook()\` with an explicit token.');
|
|
100003
|
+
}
|
|
100004
|
+
if (globalThis.__worldCapabilities?.hookForceClaim !== true) {
|
|
100005
|
+
var unsupportedForceError = new Error('The configured World does not support \`experimental_force\` for Hooks.');
|
|
100006
|
+
unsupportedForceError.name = "FatalError";
|
|
100007
|
+
unsupportedForceError.fatal = true;
|
|
100008
|
+
throw unsupportedForceError;
|
|
100009
|
+
}
|
|
100010
|
+
}
|
|
99349
100011
|
var token = options.token || globalThis.__generateNanoid();
|
|
99350
100012
|
var correlationId = "hook_" + globalThis.__generateUlid();
|
|
99351
100013
|
var isDisposed = false;
|
|
@@ -99382,6 +100044,7 @@ globalThis[Symbol.for("WORKFLOW_CREATE_HOOK")] = function(options) {
|
|
|
99382
100044
|
token: token,
|
|
99383
100045
|
tokenRetentionUntil: tokenRetentionUntil,
|
|
99384
100046
|
isWebhook: !!options.isWebhook,
|
|
100047
|
+
force: options.experimental_force === true,
|
|
99385
100048
|
metadata: options.metadata,
|
|
99386
100049
|
hasCreatedEvent: false,
|
|
99387
100050
|
};
|
|
@@ -99397,6 +100060,11 @@ globalThis[Symbol.for("WORKFLOW_CREATE_HOOK")] = function(options) {
|
|
|
99397
100060
|
token: token,
|
|
99398
100061
|
created: false,
|
|
99399
100062
|
conflict: null,
|
|
100063
|
+
// Set by the host on a hook_disposed{forceClaimedBy}: another run took
|
|
100064
|
+
// the token. Buffered payloads (delivered before the takeover) are still
|
|
100065
|
+
// drained; every await after them rejects with this error.
|
|
100066
|
+
forceClaimed: null,
|
|
100067
|
+
force: options.experimental_force === true,
|
|
99400
100068
|
getConflictResolvers: [],
|
|
99401
100069
|
};
|
|
99402
100070
|
|
|
@@ -99410,6 +100078,10 @@ globalThis[Symbol.for("WORKFLOW_CREATE_HOOK")] = function(options) {
|
|
|
99410
100078
|
if (buf && buf.length > 0) {
|
|
99411
100079
|
return Promise.resolve(buf.shift());
|
|
99412
100080
|
}
|
|
100081
|
+
var claimedState = globalThis.__hooks[correlationId];
|
|
100082
|
+
if (claimedState && claimedState.forceClaimed) {
|
|
100083
|
+
return Promise.reject(claimedState.forceClaimed);
|
|
100084
|
+
}
|
|
99413
100085
|
return new Promise(function(resolve, reject) {
|
|
99414
100086
|
globalThis.__resolvers[correlationId] = { resolve: resolve, reject: reject };
|
|
99415
100087
|
});
|
|
@@ -99425,7 +100097,9 @@ globalThis[Symbol.for("WORKFLOW_CREATE_HOOK")] = function(options) {
|
|
|
99425
100097
|
// hook_disposed here would be rejected by the world's
|
|
99426
100098
|
// hook-existence validation.
|
|
99427
100099
|
var state = globalThis.__hooks[correlationId];
|
|
99428
|
-
|
|
100100
|
+
// A force-claimed hook is already disposed \u2014 the takeover journaled
|
|
100101
|
+
// its hook_disposed \u2014 so there is nothing left to dispose either.
|
|
100102
|
+
if (!state || (!state.conflict && !state.forceClaimed)) {
|
|
99429
100103
|
// Signal to the entrypoint to create a hook_disposed event. The
|
|
99430
100104
|
// token is carried so the entrypoint can order same-token hook
|
|
99431
100105
|
// operations sequentially (a dispose must release the token before
|
|
@@ -99817,9 +100491,19 @@ async function dispatchPendingOps(params) {
|
|
|
99817
100491
|
isWebhook: hook.isWebhook,
|
|
99818
100492
|
// System hooks (AbortController) are exempt from user
|
|
99819
100493
|
// token namespace conflict checks.
|
|
99820
|
-
...hook.isSystem ? { isSystem: true } : {}
|
|
100494
|
+
...hook.isSystem ? { isSystem: true } : {},
|
|
100495
|
+
...hook.force ? { force: true } : {}
|
|
99821
100496
|
}
|
|
99822
100497
|
}, hookDeltaCursor !== void 0 ? { sinceCursor: hookDeltaCursor } : void 0);
|
|
100498
|
+
if (result2.hook?.claimedFrom) {
|
|
100499
|
+
const outcome = await publishForceClaimVictimWake(world, runId, result2.hook);
|
|
100500
|
+
runtimeLogger2.info("Hook token force-claimed from another run", {
|
|
100501
|
+
workflowRunId: runId,
|
|
100502
|
+
hookId: hook.correlationId,
|
|
100503
|
+
victimRunId: result2.hook.claimedFrom.runId,
|
|
100504
|
+
victimWake: outcome
|
|
100505
|
+
});
|
|
100506
|
+
}
|
|
99823
100507
|
if (result2.event?.eventType === "hook_conflict") {
|
|
99824
100508
|
await queueMessage(world, getWorkflowQueueName2(workflowRun.workflowName, namespace), {
|
|
99825
100509
|
runId,
|
|
@@ -99908,16 +100592,23 @@ async function dispatchPendingOps(params) {
|
|
|
99908
100592
|
hookOpsByToken.set(key, [op]);
|
|
99909
100593
|
}
|
|
99910
100594
|
}
|
|
99911
|
-
|
|
99912
|
-
|
|
99913
|
-
|
|
99914
|
-
|
|
99915
|
-
|
|
99916
|
-
|
|
99917
|
-
await processHookDisposeOp(op);
|
|
99918
|
-
}
|
|
100595
|
+
const runHookGroup = /* @__PURE__ */ __name(async (group) => {
|
|
100596
|
+
for (const op of group) {
|
|
100597
|
+
if (op.type === "hook") {
|
|
100598
|
+
await processHookOp(op);
|
|
100599
|
+
} else {
|
|
100600
|
+
await processHookDisposeOp(op);
|
|
99919
100601
|
}
|
|
99920
|
-
}
|
|
100602
|
+
}
|
|
100603
|
+
}, "runHookGroup");
|
|
100604
|
+
const hookGroups = [...hookOpsByToken.values()];
|
|
100605
|
+
const holdsForcedCreation = /* @__PURE__ */ __name((group) => group.some((op) => op.type === "hook" && op.force === true && !op.hasCreatedEvent), "holdsForcedCreation");
|
|
100606
|
+
for (const group of hookGroups.filter(holdsForcedCreation)) {
|
|
100607
|
+
await runHookGroup(group);
|
|
100608
|
+
}
|
|
100609
|
+
for (const group of hookGroups) {
|
|
100610
|
+
if (!holdsForcedCreation(group))
|
|
100611
|
+
opsPromises.push(runHookGroup(group));
|
|
99921
100612
|
}
|
|
99922
100613
|
for (const op of pendingOperations) {
|
|
99923
100614
|
if (op.type === "step" && !op.hasCreatedEvent && !skipStepCreation?.has(op.correlationId)) {
|
|
@@ -100149,6 +100840,7 @@ async function runWorkflowWithQuickJS(params) {
|
|
|
100149
100840
|
events = allEvents;
|
|
100150
100841
|
loadedCursor = cursor;
|
|
100151
100842
|
}
|
|
100843
|
+
await republishOwedForceClaimVictimWake(world, runId, events);
|
|
100152
100844
|
const logView = new QuickJSLogView(events, loadedCursor);
|
|
100153
100845
|
const createEvent = /* @__PURE__ */ __name(async (data, eventParams) => {
|
|
100154
100846
|
const result3 = await world.events.create(runId, data, {
|
|
@@ -100558,7 +101250,7 @@ async function runWorkflowWithQuickJS(params) {
|
|
|
100558
101250
|
// attempt.
|
|
100559
101251
|
authoritativeAttempt: 1,
|
|
100560
101252
|
...inlineDeltaSinceCursor !== void 0 ? { inlineDeltaSinceCursor } : {}
|
|
100561
|
-
}))())));
|
|
101253
|
+
}))(), "debug")));
|
|
100562
101254
|
} finally {
|
|
100563
101255
|
budget.resume();
|
|
100564
101256
|
}
|
|
@@ -100893,6 +101585,7 @@ var init_quickjs_entrypoint = __esm({
|
|
|
100893
101585
|
init_constants3();
|
|
100894
101586
|
init_get_port_lazy();
|
|
100895
101587
|
init_helpers3();
|
|
101588
|
+
init_hook_wake2();
|
|
100896
101589
|
init_lifecycle_hooks();
|
|
100897
101590
|
init_quickjs_log_view();
|
|
100898
101591
|
init_quickjs_runtime();
|
|
@@ -101341,6 +102034,7 @@ var StepNotRegisteredError;
|
|
|
101341
102034
|
var WorkflowNotRegisteredError;
|
|
101342
102035
|
var WorkflowRunNotFoundError;
|
|
101343
102036
|
var HookConflictError;
|
|
102037
|
+
var HookForceClaimedError;
|
|
101344
102038
|
var HookNotFoundError;
|
|
101345
102039
|
var EntityConflictError;
|
|
101346
102040
|
var RunExpiredError;
|
|
@@ -101353,6 +102047,7 @@ var RetryableError;
|
|
|
101353
102047
|
var FATAL_ERROR_KEY;
|
|
101354
102048
|
var RETRYABLE_ERROR_KEY;
|
|
101355
102049
|
var HOOK_CONFLICT_ERROR_KEY;
|
|
102050
|
+
var HOOK_FORCE_CLAIMED_ERROR_KEY;
|
|
101356
102051
|
var RUNTIME_DECRYPTION_ERROR_KEY;
|
|
101357
102052
|
var STREAM_ERROR_KEY;
|
|
101358
102053
|
var init_dist2 = __esm2({
|
|
@@ -101374,6 +102069,7 @@ var init_dist2 = __esm2({
|
|
|
101374
102069
|
FETCH_IN_WORKFLOW_FUNCTION: "fetch-in-workflow",
|
|
101375
102070
|
TIMEOUT_FUNCTIONS_IN_WORKFLOW: "timeout-in-workflow",
|
|
101376
102071
|
HOOK_CONFLICT: "hook-conflict",
|
|
102072
|
+
HOOK_FORCE_CLAIMED: "hook-force-claimed",
|
|
101377
102073
|
CORRUPTED_EVENT_LOG: "corrupted-event-log",
|
|
101378
102074
|
REPLAY_DIVERGENCE: "replay-divergence",
|
|
101379
102075
|
STEP_NOT_REGISTERED: "step-not-registered",
|
|
@@ -101633,6 +102329,33 @@ Caused by: ${options.cause.stack}`;
|
|
|
101633
102329
|
return isError(value) && value.name === "HookConflictError";
|
|
101634
102330
|
}
|
|
101635
102331
|
};
|
|
102332
|
+
HookForceClaimedError = class extends WorkflowError {
|
|
102333
|
+
static {
|
|
102334
|
+
__name(this, "HookForceClaimedError");
|
|
102335
|
+
}
|
|
102336
|
+
static {
|
|
102337
|
+
__name2(this, "HookForceClaimedError");
|
|
102338
|
+
}
|
|
102339
|
+
token;
|
|
102340
|
+
/** The run that took the token. */
|
|
102341
|
+
claimedByRunId;
|
|
102342
|
+
/** The hook (in `claimedByRunId`) the token now belongs to. */
|
|
102343
|
+
claimedByHookId;
|
|
102344
|
+
constructor(token, claimedByRunId, claimedByHookId) {
|
|
102345
|
+
super(`Hook token "${token}" was force-claimed by another workflow (run "${claimedByRunId}")`, {
|
|
102346
|
+
slug: ERROR_SLUGS.HOOK_FORCE_CLAIMED
|
|
102347
|
+
});
|
|
102348
|
+
this.name = "HookForceClaimedError";
|
|
102349
|
+
this.token = token;
|
|
102350
|
+
this.claimedByRunId = claimedByRunId;
|
|
102351
|
+
if (claimedByHookId !== void 0) {
|
|
102352
|
+
this.claimedByHookId = claimedByHookId;
|
|
102353
|
+
}
|
|
102354
|
+
}
|
|
102355
|
+
static is(value) {
|
|
102356
|
+
return isError(value) && value.name === "HookForceClaimedError";
|
|
102357
|
+
}
|
|
102358
|
+
};
|
|
101636
102359
|
HookNotFoundError = class extends WorkflowError {
|
|
101637
102360
|
static {
|
|
101638
102361
|
__name(this, "HookNotFoundError");
|
|
@@ -101812,6 +102535,7 @@ Caused by: ${options.cause.stack}`;
|
|
|
101812
102535
|
FATAL_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//FatalError");
|
|
101813
102536
|
RETRYABLE_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RetryableError");
|
|
101814
102537
|
HOOK_CONFLICT_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookConflictError");
|
|
102538
|
+
HOOK_FORCE_CLAIMED_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError");
|
|
101815
102539
|
RUNTIME_DECRYPTION_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RuntimeDecryptionError");
|
|
101816
102540
|
STREAM_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//StreamError");
|
|
101817
102541
|
if (typeof globalThis !== "undefined") {
|
|
@@ -101839,6 +102563,14 @@ Caused by: ${options.cause.stack}`;
|
|
|
101839
102563
|
configurable: false
|
|
101840
102564
|
});
|
|
101841
102565
|
}
|
|
102566
|
+
if (!Object.hasOwn(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY)) {
|
|
102567
|
+
Object.defineProperty(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY, {
|
|
102568
|
+
value: HookForceClaimedError,
|
|
102569
|
+
writable: false,
|
|
102570
|
+
enumerable: false,
|
|
102571
|
+
configurable: false
|
|
102572
|
+
});
|
|
102573
|
+
}
|
|
101842
102574
|
if (!Object.hasOwn(globalThis, RUNTIME_DECRYPTION_ERROR_KEY)) {
|
|
101843
102575
|
Object.defineProperty(globalThis, RUNTIME_DECRYPTION_ERROR_KEY, {
|
|
101844
102576
|
value: RuntimeDecryptionError,
|
|
@@ -101915,7 +102647,7 @@ var SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT;
|
|
|
101915
102647
|
var SPEC_VERSION_SUPPORTS_ATTRIBUTES;
|
|
101916
102648
|
var SPEC_VERSION_SUPPORTS_COMPRESSION;
|
|
101917
102649
|
var SPEC_VERSION_SUPPORTS_SLOT_IDENTITY;
|
|
101918
|
-
var
|
|
102650
|
+
var SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM;
|
|
101919
102651
|
var SPEC_VERSION_CURRENT;
|
|
101920
102652
|
var SPEC_VERSION_MAX_SUPPORTED;
|
|
101921
102653
|
var init_spec_version = __esm2({
|
|
@@ -101927,9 +102659,9 @@ var init_spec_version = __esm2({
|
|
|
101927
102659
|
SPEC_VERSION_SUPPORTS_ATTRIBUTES = 4;
|
|
101928
102660
|
SPEC_VERSION_SUPPORTS_COMPRESSION = 5;
|
|
101929
102661
|
SPEC_VERSION_SUPPORTS_SLOT_IDENTITY = 6;
|
|
101930
|
-
|
|
101931
|
-
SPEC_VERSION_CURRENT =
|
|
101932
|
-
SPEC_VERSION_MAX_SUPPORTED =
|
|
102662
|
+
SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM = 8;
|
|
102663
|
+
SPEC_VERSION_CURRENT = SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM;
|
|
102664
|
+
SPEC_VERSION_MAX_SUPPORTED = SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM;
|
|
101933
102665
|
__name2(isLegacySpecVersion, "isLegacySpecVersion");
|
|
101934
102666
|
}
|
|
101935
102667
|
});
|
|
@@ -126890,7 +127622,30 @@ var init_events = __esm2({
|
|
|
126890
127622
|
tokenRetentionUntil: external_exports.coerce.date().optional(),
|
|
126891
127623
|
metadata: SerializedDataSchema.optional(),
|
|
126892
127624
|
isWebhook: external_exports.boolean().optional(),
|
|
126893
|
-
isSystem: external_exports.boolean().optional()
|
|
127625
|
+
isSystem: external_exports.boolean().optional(),
|
|
127626
|
+
/**
|
|
127627
|
+
* `createHook({ experimental_force: true })`: when the token belongs to
|
|
127628
|
+
* another live run, the World takes it over — journaling
|
|
127629
|
+
* `hook_disposed{forceClaimedBy}` in that run's log and re-pointing the
|
|
127630
|
+
* token — instead of answering `hook_conflict`. Requires the
|
|
127631
|
+
* `hookForceClaim` capability.
|
|
127632
|
+
*/
|
|
127633
|
+
force: external_exports.boolean().optional(),
|
|
127634
|
+
/**
|
|
127635
|
+
* World-written on a forced creation that did take a token over: the
|
|
127636
|
+
* run and hook it was taken from, plus what a queue message to that run
|
|
127637
|
+
* needs (`workflowName`, `deploymentId`, `runSpecVersion`). Absent when
|
|
127638
|
+
* the token was free. The wake-targeting fields are in the LOG, not only
|
|
127639
|
+
* on the hook entity, so a replay can republish the victim's wake from
|
|
127640
|
+
* the row alone; see `publishForceClaimVictimWake` in @workflow/core.
|
|
127641
|
+
*/
|
|
127642
|
+
forceClaimedFrom: external_exports.object({
|
|
127643
|
+
runId: external_exports.string(),
|
|
127644
|
+
hookId: external_exports.string(),
|
|
127645
|
+
workflowName: external_exports.string().optional(),
|
|
127646
|
+
deploymentId: external_exports.string().optional(),
|
|
127647
|
+
runSpecVersion: external_exports.number().optional()
|
|
127648
|
+
}).optional()
|
|
126894
127649
|
})
|
|
126895
127650
|
}));
|
|
126896
127651
|
HookReceivedEventSchema = external_exports.compile(BaseEventSchema.extend({
|
|
@@ -126905,7 +127660,17 @@ var init_events = __esm2({
|
|
|
126905
127660
|
eventType: external_exports.literal("hook_disposed"),
|
|
126906
127661
|
correlationId: external_exports.string(),
|
|
126907
127662
|
eventData: external_exports.object({
|
|
126908
|
-
token: external_exports.string().optional()
|
|
127663
|
+
token: external_exports.string().optional(),
|
|
127664
|
+
/**
|
|
127665
|
+
* World-written: this disposal was not the run's own. Another run
|
|
127666
|
+
* took the hook's token with `experimental_force`, and this names
|
|
127667
|
+
* it. The hook consumer rejects the hook's awaiters with
|
|
127668
|
+
* `HookForceClaimedError` when it reads this row.
|
|
127669
|
+
*/
|
|
127670
|
+
forceClaimedBy: external_exports.object({
|
|
127671
|
+
runId: external_exports.string(),
|
|
127672
|
+
hookId: external_exports.string()
|
|
127673
|
+
}).optional()
|
|
126909
127674
|
}).optional()
|
|
126910
127675
|
}));
|
|
126911
127676
|
HookConflictEventSchema = external_exports.compile(BaseEventSchema.extend({
|
|
@@ -126915,7 +127680,18 @@ var init_events = __esm2({
|
|
|
126915
127680
|
token: external_exports.string(),
|
|
126916
127681
|
// TODO: Make this required once all persisted hook_conflict events and
|
|
126917
127682
|
// remote World implementations always include the active hook owner's run ID.
|
|
126918
|
-
conflictingRunId: external_exports.string().optional()
|
|
127683
|
+
conflictingRunId: external_exports.string().optional(),
|
|
127684
|
+
/**
|
|
127685
|
+
* Set when the creation asked for `force` and the World declined to take
|
|
127686
|
+
* the token over. `victim-spec-version`: the run holding the token was
|
|
127687
|
+
* started at a spec version below
|
|
127688
|
+
* `SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM`, so its runtime would not
|
|
127689
|
+
* understand the involuntary disposal — the forced hook gets the
|
|
127690
|
+
* ordinary `HookConflictError` it opted out of instead of stranding
|
|
127691
|
+
* that run. Absent on a conflict answered by a World that does not
|
|
127692
|
+
* implement forcing at all.
|
|
127693
|
+
*/
|
|
127694
|
+
forceRefusedReason: external_exports.literal("victim-spec-version").optional()
|
|
126919
127695
|
})
|
|
126920
127696
|
}));
|
|
126921
127697
|
NoopEventSchema = external_exports.compile(BaseEventSchema.extend({
|
|
@@ -127801,6 +128577,7 @@ var HookResumeContextSchema;
|
|
|
127801
128577
|
var HOOK_RESUME_INPUT_VERSION;
|
|
127802
128578
|
var HOOK_RESUME_DEDUP_VERSION;
|
|
127803
128579
|
var HookResumeCapabilitiesSchema;
|
|
128580
|
+
var HookClaimedFromSchema;
|
|
127804
128581
|
var HookSchema;
|
|
127805
128582
|
var init_hooks = __esm2({
|
|
127806
128583
|
"../world/dist/hooks.js"() {
|
|
@@ -127842,6 +128619,13 @@ var init_hooks = __esm2({
|
|
|
127842
128619
|
// is engaged.
|
|
127843
128620
|
hookResumeDedupVersion: external_exports.number()
|
|
127844
128621
|
}));
|
|
128622
|
+
HookClaimedFromSchema = external_exports.compile(external_exports.object({
|
|
128623
|
+
runId: external_exports.string(),
|
|
128624
|
+
hookId: external_exports.string(),
|
|
128625
|
+
workflowName: external_exports.string().optional(),
|
|
128626
|
+
deploymentId: external_exports.string().optional(),
|
|
128627
|
+
runSpecVersion: external_exports.number().optional()
|
|
128628
|
+
}));
|
|
127845
128629
|
HookSchema = external_exports.compile(external_exports.object({
|
|
127846
128630
|
runId: external_exports.string(),
|
|
127847
128631
|
hookId: external_exports.string(),
|
|
@@ -127869,7 +128653,12 @@ var init_hooks = __esm2({
|
|
|
127869
128653
|
// `resumeHook()` gates its lazy path on this being present and
|
|
127870
128654
|
// current. Absent against an older/rolled-back server or when the kill switch
|
|
127871
128655
|
// is active.
|
|
127872
|
-
resumeCapabilities: HookResumeCapabilitiesSchema.optional()
|
|
128656
|
+
resumeCapabilities: HookResumeCapabilitiesSchema.optional(),
|
|
128657
|
+
// Set when this hook took its token from another run
|
|
128658
|
+
// (`experimental_force`). The wake-targeting fields are the victim run's,
|
|
128659
|
+
// so the claimer's runtime can publish the victim's wake without reading
|
|
128660
|
+
// a run it may not be able to reach; see `HookClaimedFromSchema`.
|
|
128661
|
+
claimedFrom: HookClaimedFromSchema.optional()
|
|
127873
128662
|
}));
|
|
127874
128663
|
}
|
|
127875
128664
|
});
|
|
@@ -128607,6 +129396,20 @@ function getCommonReducers(_global2 = globalThis) {
|
|
|
128607
129396
|
}
|
|
128608
129397
|
return reduced;
|
|
128609
129398
|
}, "HookConflictError"),
|
|
129399
|
+
HookForceClaimedError: /* @__PURE__ */ __name2((value) => {
|
|
129400
|
+
const base = reduceNamedErrorSubclassBase("HookForceClaimedError", value);
|
|
129401
|
+
if (!base) return false;
|
|
129402
|
+
const reduced = {
|
|
129403
|
+
...base,
|
|
129404
|
+
token: readProperty(value, "token"),
|
|
129405
|
+
claimedByRunId: readProperty(value, "claimedByRunId")
|
|
129406
|
+
};
|
|
129407
|
+
const claimedByHookId = readProperty(value, "claimedByHookId");
|
|
129408
|
+
if (claimedByHookId !== void 0) {
|
|
129409
|
+
reduced.claimedByHookId = claimedByHookId;
|
|
129410
|
+
}
|
|
129411
|
+
return reduced;
|
|
129412
|
+
}, "HookForceClaimedError"),
|
|
128610
129413
|
RangeError: makeErrorSubclassReducer("RangeError"),
|
|
128611
129414
|
ReferenceError: makeErrorSubclassReducer("ReferenceError"),
|
|
128612
129415
|
// RetryableError carries an extra `retryAfter` Date that we serialize as
|
|
@@ -128782,6 +129585,15 @@ function getCommonRevivers(global2 = globalThis) {
|
|
|
128782
129585
|
}
|
|
128783
129586
|
return error612;
|
|
128784
129587
|
}, "HookConflictError"),
|
|
129588
|
+
HookForceClaimedError: /* @__PURE__ */ __name2((value) => {
|
|
129589
|
+
const Ctor = global2[/* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError")] ?? HookForceClaimedError;
|
|
129590
|
+
const error612 = new Ctor(value.token, value.claimedByRunId, value.claimedByHookId);
|
|
129591
|
+
if (value.stack !== void 0) error612.stack = value.stack;
|
|
129592
|
+
if ("cause" in value) {
|
|
129593
|
+
error612.cause = value.cause;
|
|
129594
|
+
}
|
|
129595
|
+
return error612;
|
|
129596
|
+
}, "HookForceClaimedError"),
|
|
128785
129597
|
RangeError: makeErrorSubclassReviver(global2, "RangeError"),
|
|
128786
129598
|
ReferenceError: makeErrorSubclassReviver(global2, "ReferenceError"),
|
|
128787
129599
|
RetryableError: /* @__PURE__ */ __name2((value) => {
|
|
@@ -134364,7 +135176,7 @@ var version2;
|
|
|
134364
135176
|
var init_version = __esm2({
|
|
134365
135177
|
"../core/dist/version.js"() {
|
|
134366
135178
|
"use strict";
|
|
134367
|
-
version2 = "5.0.0-beta.
|
|
135179
|
+
version2 = "5.0.0-beta.56";
|
|
134368
135180
|
}
|
|
134369
135181
|
});
|
|
134370
135182
|
function getWorkflowQueueName(workflowName, namespace) {
|
|
@@ -134551,6 +135363,56 @@ var init_helpers = __esm2({
|
|
|
134551
135363
|
__name2(healthCheck, "healthCheck");
|
|
134552
135364
|
}
|
|
134553
135365
|
});
|
|
135366
|
+
function isRetryableWakeError(error612, isDeploymentUnavailableError) {
|
|
135367
|
+
if (isDeploymentUnavailableError?.(error612)) return false;
|
|
135368
|
+
const status = error612 ?? {};
|
|
135369
|
+
const code22 = status.status ?? status.statusCode;
|
|
135370
|
+
if (typeof code22 === "number") {
|
|
135371
|
+
return code22 >= 500 || code22 === 408 || code22 === 429;
|
|
135372
|
+
}
|
|
135373
|
+
const name = error612?.name;
|
|
135374
|
+
return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
|
|
135375
|
+
}
|
|
135376
|
+
__name(isRetryableWakeError, "isRetryableWakeError");
|
|
135377
|
+
async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
|
|
135378
|
+
let lastError;
|
|
135379
|
+
for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
|
|
135380
|
+
try {
|
|
135381
|
+
await publish();
|
|
135382
|
+
return;
|
|
135383
|
+
} catch (error612) {
|
|
135384
|
+
lastError = error612;
|
|
135385
|
+
if (!isRetryableWakeError(error612, isDeploymentUnavailableError)) break;
|
|
135386
|
+
const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
|
|
135387
|
+
if (delayMs !== void 0) {
|
|
135388
|
+
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
135389
|
+
}
|
|
135390
|
+
}
|
|
135391
|
+
}
|
|
135392
|
+
if (HookNotFoundError.is(lastError)) {
|
|
135393
|
+
throw new WorkflowRuntimeError("The hook resume was committed, but its workflow wake could not be published", {
|
|
135394
|
+
cause: lastError
|
|
135395
|
+
});
|
|
135396
|
+
}
|
|
135397
|
+
throw lastError;
|
|
135398
|
+
}
|
|
135399
|
+
__name(publishHookWakeWithRetry, "publishHookWakeWithRetry");
|
|
135400
|
+
var HOOK_WAKE_RETRY_DELAYS_MS;
|
|
135401
|
+
var init_hook_wake = __esm2({
|
|
135402
|
+
"../core/dist/runtime/hook-wake.js"() {
|
|
135403
|
+
"use strict";
|
|
135404
|
+
init_dist2();
|
|
135405
|
+
init_dist4();
|
|
135406
|
+
init_logger();
|
|
135407
|
+
init_helpers();
|
|
135408
|
+
HOOK_WAKE_RETRY_DELAYS_MS = [
|
|
135409
|
+
25,
|
|
135410
|
+
100
|
|
135411
|
+
];
|
|
135412
|
+
__name2(isRetryableWakeError, "isRetryableWakeError");
|
|
135413
|
+
__name2(publishHookWakeWithRetry, "publishHookWakeWithRetry");
|
|
135414
|
+
}
|
|
135415
|
+
});
|
|
134554
135416
|
var HookInvocationSchema;
|
|
134555
135417
|
var HookInvocationResultSchema;
|
|
134556
135418
|
var init_invocations = __esm2({
|
|
@@ -139600,40 +140462,6 @@ async function computeResumePayloadDigest(bytes) {
|
|
|
139600
140462
|
return hex32;
|
|
139601
140463
|
}
|
|
139602
140464
|
__name(computeResumePayloadDigest, "computeResumePayloadDigest");
|
|
139603
|
-
function isRetryableWakeError(error612, isDeploymentUnavailableError) {
|
|
139604
|
-
if (isDeploymentUnavailableError?.(error612)) return false;
|
|
139605
|
-
const status = error612 ?? {};
|
|
139606
|
-
const code22 = status.status ?? status.statusCode;
|
|
139607
|
-
if (typeof code22 === "number") {
|
|
139608
|
-
return code22 >= 500 || code22 === 408 || code22 === 429;
|
|
139609
|
-
}
|
|
139610
|
-
const name = error612?.name;
|
|
139611
|
-
return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
|
|
139612
|
-
}
|
|
139613
|
-
__name(isRetryableWakeError, "isRetryableWakeError");
|
|
139614
|
-
async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
|
|
139615
|
-
let lastError;
|
|
139616
|
-
for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
|
|
139617
|
-
try {
|
|
139618
|
-
await publish();
|
|
139619
|
-
return;
|
|
139620
|
-
} catch (error612) {
|
|
139621
|
-
lastError = error612;
|
|
139622
|
-
if (!isRetryableWakeError(error612, isDeploymentUnavailableError)) break;
|
|
139623
|
-
const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
|
|
139624
|
-
if (delayMs !== void 0) {
|
|
139625
|
-
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
139626
|
-
}
|
|
139627
|
-
}
|
|
139628
|
-
}
|
|
139629
|
-
if (HookNotFoundError.is(lastError)) {
|
|
139630
|
-
throw new WorkflowRuntimeError("The hook resume was committed, but its workflow wake could not be published", {
|
|
139631
|
-
cause: lastError
|
|
139632
|
-
});
|
|
139633
|
-
}
|
|
139634
|
-
throw lastError;
|
|
139635
|
-
}
|
|
139636
|
-
__name(publishHookWakeWithRetry, "publishHookWakeWithRetry");
|
|
139637
140465
|
function resumeContextFromRun(run22) {
|
|
139638
140466
|
const coreVersion = run22.executionContext?.workflowCoreVersion;
|
|
139639
140467
|
const traceCarrier = run22.executionContext?.traceCarrier;
|
|
@@ -139723,164 +140551,269 @@ async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
|
|
|
139723
140551
|
return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
|
|
139724
140552
|
}
|
|
139725
140553
|
__name(resumeHook, "resumeHook");
|
|
139726
|
-
async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
|
|
140554
|
+
async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, webhookOnly = false) {
|
|
139727
140555
|
return await waitedUntil(() => {
|
|
139728
140556
|
return trace("hook.resume", async (span) => {
|
|
139729
140557
|
const world = await getWorldLazy();
|
|
139730
|
-
|
|
139731
|
-
|
|
139732
|
-
|
|
139733
|
-
|
|
139734
|
-
|
|
139735
|
-
|
|
139736
|
-
|
|
139737
|
-
|
|
139738
|
-
|
|
139739
|
-
|
|
139740
|
-
"workflow.hook.resume_context_source": info.source
|
|
139741
|
-
});
|
|
139742
|
-
if (info.run && isTerminalWorkflowRunStatus(info.run.status)) {
|
|
139743
|
-
throw new HookNotFoundError(hook.token);
|
|
139744
|
-
}
|
|
139745
|
-
const capabilities = getRunCapabilities(resumeContext.workflowCoreVersion);
|
|
139746
|
-
let payloadKey;
|
|
139747
|
-
const runPublicKey = encryptionKeyOverride ? (
|
|
139748
|
-
// hydrate hook metadata), so sealing would add an ECDH for no
|
|
139749
|
-
// saved round trip. Reuse what it resolved.
|
|
139750
|
-
void 0
|
|
139751
|
-
) : decodeRunPublicKey(resumeContext.encryptionPublicKey);
|
|
139752
|
-
if (runPublicKey) {
|
|
139753
|
-
payloadKey = sealTo(runPublicKey);
|
|
139754
|
-
} else {
|
|
139755
|
-
let encryptionKey = encryptionKeyOverride ?? await resolveHookEncryptionKey(hook, info);
|
|
139756
|
-
if (!capabilities.supportedFormats.has(SerializationFormat.ENCRYPTED)) {
|
|
139757
|
-
encryptionKey = void 0;
|
|
139758
|
-
}
|
|
139759
|
-
payloadKey = encryptionKey;
|
|
139760
|
-
}
|
|
139761
|
-
const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION && capabilities.supportedFormats.has(SerializationFormat.GZIP);
|
|
139762
|
-
const ops = [];
|
|
139763
|
-
const readbackOps = [];
|
|
139764
|
-
const v1Compat = isLegacySpecVersion(hook.specVersion);
|
|
139765
|
-
const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
|
|
139766
|
-
await Promise.all(ops.map((op) => op.catch((error612) => {
|
|
139767
|
-
if (error612 !== void 0) throw error612;
|
|
139768
|
-
})));
|
|
139769
|
-
safeWaitUntil(Promise.all(readbackOps), (err) => {
|
|
139770
|
-
if (err === void 0) return;
|
|
139771
|
-
runtimeLogger.warn("Background readback of hook payload failed", {
|
|
139772
|
-
workflowRunId: hook.runId,
|
|
139773
|
-
hookId: hook.hookId,
|
|
139774
|
-
error: err instanceof Error ? err.message : String(err)
|
|
139775
|
-
});
|
|
139776
|
-
});
|
|
139777
|
-
span?.setAttributes({
|
|
139778
|
-
...WorkflowName(resumeContext.workflowName)
|
|
139779
|
-
});
|
|
139780
|
-
const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
|
|
139781
|
-
if (originLink) {
|
|
139782
|
-
span?.addLink?.(originLink);
|
|
139783
|
-
}
|
|
139784
|
-
if (world.capabilities?.invoke === true && !v1Compat && dehydratedPayload instanceof Uint8Array) {
|
|
139785
|
-
if (!world.invoke) {
|
|
139786
|
-
throw new WorkflowRuntimeError("World advertises invoke without implementing it");
|
|
139787
|
-
}
|
|
140558
|
+
const token = typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token;
|
|
140559
|
+
let target2 = tokenOrHook;
|
|
140560
|
+
let fresh = hookFreshlyLookedUp;
|
|
140561
|
+
let keyOverride = encryptionKeyOverride;
|
|
140562
|
+
let redirects = 0;
|
|
140563
|
+
let lookupsAfterRedirect = 0;
|
|
140564
|
+
const MAX_LOOKUPS_AFTER_REDIRECT = 5;
|
|
140565
|
+
const resumeId = generateResumeId();
|
|
140566
|
+
const assertResendable = /* @__PURE__ */ __name2((cause) => {
|
|
140567
|
+
if (payload instanceof Request && payload.body !== null && payload.bodyUsed) {
|
|
139788
140568
|
span?.setAttributes({
|
|
139789
|
-
"workflow.hook.
|
|
140569
|
+
"workflow.hook.resume_redirect_unresendable": true
|
|
139790
140570
|
});
|
|
139791
|
-
|
|
139792
|
-
|
|
139793
|
-
version: 1,
|
|
139794
|
-
hookId: hook.hookId,
|
|
139795
|
-
token: hook.token,
|
|
139796
|
-
payload: dehydratedPayload
|
|
139797
|
-
}, {
|
|
139798
|
-
idempotencyKey: generateResumeId()
|
|
139799
|
-
}));
|
|
139800
|
-
if (result2.status === "rejected") {
|
|
139801
|
-
if (result2.code === "HOOK_NOT_FOUND") throw new HookNotFoundError(hook.token);
|
|
139802
|
-
throw new WorkflowRuntimeError("Executor rejected the hook invocation input");
|
|
139803
|
-
}
|
|
139804
|
-
span?.setAttributes(HookResumeCommitted(true));
|
|
139805
|
-
return asLazyMetadataHook(hook);
|
|
139806
|
-
}
|
|
139807
|
-
const queueName = getWorkflowQueueName(resumeContext.workflowName);
|
|
139808
|
-
const queueOptions = {
|
|
139809
|
-
deploymentId: resumeContext.deploymentId,
|
|
139810
|
-
specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY
|
|
139811
|
-
};
|
|
139812
|
-
const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION || world.capabilities?.hookResumeDedup === true;
|
|
139813
|
-
const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
|
|
139814
|
-
span?.setAttributes({
|
|
139815
|
-
"workflow.hook.resume_strategy": "sequential"
|
|
139816
|
-
});
|
|
139817
|
-
const resumeId = canClaimResume ? generateResumeId() : void 0;
|
|
139818
|
-
const payloadDigest = canClaimResume ? await computeResumePayloadDigest(dehydratedPayload) : void 0;
|
|
139819
|
-
if (resumeId) {
|
|
139820
|
-
span?.setAttributes({
|
|
139821
|
-
"workflow.hook.resume_id": resumeId
|
|
140571
|
+
throw new WorkflowRuntimeError(`Hook token "${token}" changed owner while this webhook request was being delivered; a request body can be sent only once and it was not delivered anywhere \u2014 retry the request, which will reach the token's new owner`, {
|
|
140572
|
+
cause
|
|
139822
140573
|
});
|
|
139823
140574
|
}
|
|
139824
|
-
|
|
140575
|
+
}, "assertResendable");
|
|
140576
|
+
for (; ; ) {
|
|
139825
140577
|
try {
|
|
139826
|
-
await world
|
|
139827
|
-
eventType: "hook_received",
|
|
139828
|
-
specVersion: SPEC_VERSION_CURRENT,
|
|
139829
|
-
correlationId: hook.hookId,
|
|
139830
|
-
eventData: {
|
|
139831
|
-
...v1Compat ? {} : {
|
|
139832
|
-
token: hook.token
|
|
139833
|
-
},
|
|
139834
|
-
payload: dehydratedPayload
|
|
139835
|
-
}
|
|
139836
|
-
}, {
|
|
139837
|
-
v1Compat,
|
|
139838
|
-
...resumeId && payloadDigest ? {
|
|
139839
|
-
resumeId,
|
|
139840
|
-
resumePayloadDigest: payloadDigest
|
|
139841
|
-
} : {}
|
|
139842
|
-
});
|
|
140578
|
+
return await resumeHookAttempt(world, span, target2, payload, keyOverride, fresh, resumeRequestedAtMs, resumeId, webhookOnly);
|
|
139843
140579
|
} catch (err) {
|
|
139844
|
-
if (
|
|
139845
|
-
throw
|
|
140580
|
+
if (err !== null && typeof err === "object" && notFoundReasons.get(err) === "not-webhook") {
|
|
140581
|
+
throw err;
|
|
140582
|
+
}
|
|
140583
|
+
if (redirects >= MAX_FORCE_CLAIM_REDIRECTS) {
|
|
140584
|
+
if (HookForceClaimedError.is(err)) {
|
|
140585
|
+
span?.setAttributes({
|
|
140586
|
+
"workflow.hook.resume_redirects_exhausted": true
|
|
140587
|
+
});
|
|
140588
|
+
throw new WorkflowRuntimeError(`Hook token "${token}" changed owner ${redirects} times while this resume was in flight; nothing was delivered \u2014 retry the resume`, {
|
|
140589
|
+
cause: err
|
|
140590
|
+
});
|
|
140591
|
+
}
|
|
140592
|
+
throw err;
|
|
140593
|
+
}
|
|
140594
|
+
if (HookForceClaimedError.is(err)) {
|
|
140595
|
+
assertResendable(err);
|
|
140596
|
+
redirects++;
|
|
140597
|
+
span?.setAttributes({
|
|
140598
|
+
"workflow.hook.resume_redirects": redirects,
|
|
140599
|
+
"workflow.hook.resume_redirect_to_run": err.claimedByRunId
|
|
140600
|
+
});
|
|
140601
|
+
target2 = token;
|
|
140602
|
+
fresh = true;
|
|
140603
|
+
keyOverride = void 0;
|
|
140604
|
+
lookupsAfterRedirect = 0;
|
|
140605
|
+
continue;
|
|
140606
|
+
}
|
|
140607
|
+
if (HookNotFoundError.is(err) && redirects > 0 && typeof target2 === "string" && lookupsAfterRedirect < MAX_LOOKUPS_AFTER_REDIRECT) {
|
|
140608
|
+
assertResendable(err);
|
|
140609
|
+
lookupsAfterRedirect++;
|
|
140610
|
+
await new Promise((resolve3) => setTimeout(resolve3, 50));
|
|
140611
|
+
continue;
|
|
140612
|
+
}
|
|
140613
|
+
if (HookNotFoundError.is(err) && notFoundReasons.get(err) !== "lookup") {
|
|
140614
|
+
const attemptedHookId = typeof target2 === "string" ? void 0 : target2.hookId;
|
|
140615
|
+
let relocated;
|
|
140616
|
+
try {
|
|
140617
|
+
relocated = await world.hooks.getByToken(token);
|
|
140618
|
+
} catch (lookupError) {
|
|
140619
|
+
if (!HookNotFoundError.is(lookupError)) {
|
|
140620
|
+
runtimeLogger.warn("Hook resume: re-resolving the token after a not-found failed; surfacing the original error", {
|
|
140621
|
+
token,
|
|
140622
|
+
error: lookupError instanceof Error ? lookupError.message : String(lookupError)
|
|
140623
|
+
});
|
|
140624
|
+
}
|
|
140625
|
+
}
|
|
140626
|
+
if (relocated?.claimedFrom !== void 0 && relocated.hookId !== attemptedHookId && (attemptedHookId === void 0 || relocated.claimedFrom.hookId === attemptedHookId) && !(webhookOnly && relocated.isWebhook === false)) {
|
|
140627
|
+
assertResendable(err);
|
|
140628
|
+
redirects++;
|
|
140629
|
+
span?.setAttributes({
|
|
140630
|
+
"workflow.hook.resume_redirects": redirects,
|
|
140631
|
+
"workflow.hook.resume_redirect_to_run": relocated.runId
|
|
140632
|
+
});
|
|
140633
|
+
target2 = relocated;
|
|
140634
|
+
fresh = true;
|
|
140635
|
+
keyOverride = void 0;
|
|
140636
|
+
continue;
|
|
140637
|
+
}
|
|
139846
140638
|
}
|
|
139847
140639
|
throw err;
|
|
139848
140640
|
}
|
|
139849
|
-
span?.setAttributes(HookResumeCommitted(true));
|
|
139850
|
-
const queuePublishRequestedAtMs = Date.now();
|
|
139851
|
-
await publishHookWakeWithRetry(() => world.queue(queueName, {
|
|
139852
|
-
runId: hook.runId,
|
|
139853
|
-
traceCarrier: resumeContext.traceCarrier ?? void 0,
|
|
139854
|
-
hookResumeTiming: {
|
|
139855
|
-
resumeRequestedAtMs,
|
|
139856
|
-
queuePublishRequestedAtMs,
|
|
139857
|
-
strategy: "sequential"
|
|
139858
|
-
}
|
|
139859
|
-
}, {
|
|
139860
|
-
...queueOptions,
|
|
139861
|
-
// Dedup retried publishes whose response was lost: a
|
|
139862
|
-
// duplicate wake is harmless for correctness (deterministic
|
|
139863
|
-
// replay) but costs a full replay of the run, and the queue
|
|
139864
|
-
// accepts a repeated idempotency key by delivering only one
|
|
139865
|
-
// of the messages. Claim-less writes have no resumeId and
|
|
139866
|
-
// keep the previous behavior.
|
|
139867
|
-
...resumeId ? {
|
|
139868
|
-
idempotencyKey: `hook-${resumeId}`
|
|
139869
|
-
} : {}
|
|
139870
|
-
}), world.isDeploymentUnavailableError?.bind(world));
|
|
139871
|
-
span?.setAttributes(HookWakePublished(true));
|
|
139872
|
-
return asLazyMetadataHook(hook);
|
|
139873
|
-
} catch (err) {
|
|
139874
|
-
span?.setAttributes({
|
|
139875
|
-
...HookToken(typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token),
|
|
139876
|
-
...HookFound(false)
|
|
139877
|
-
});
|
|
139878
|
-
throw err;
|
|
139879
140641
|
}
|
|
139880
140642
|
});
|
|
139881
140643
|
});
|
|
139882
140644
|
}
|
|
139883
140645
|
__name(resumeHookImpl, "resumeHookImpl");
|
|
140646
|
+
async function resumeHookAttempt(world, span, tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, logicalResumeId, webhookOnly) {
|
|
140647
|
+
try {
|
|
140648
|
+
const suppliedToken = typeof tokenOrHook === "string";
|
|
140649
|
+
let hook;
|
|
140650
|
+
if (suppliedToken) {
|
|
140651
|
+
try {
|
|
140652
|
+
hook = await world.hooks.getByToken(tokenOrHook);
|
|
140653
|
+
} catch (lookupError) {
|
|
140654
|
+
if (HookNotFoundError.is(lookupError)) {
|
|
140655
|
+
notFoundReasons.set(lookupError, "lookup");
|
|
140656
|
+
}
|
|
140657
|
+
throw lookupError;
|
|
140658
|
+
}
|
|
140659
|
+
} else {
|
|
140660
|
+
hook = tokenOrHook;
|
|
140661
|
+
}
|
|
140662
|
+
if (webhookOnly && hook.isWebhook === false) {
|
|
140663
|
+
const notWebhook = new HookNotFoundError(hook.token);
|
|
140664
|
+
notFoundReasons.set(notWebhook, "not-webhook");
|
|
140665
|
+
throw notWebhook;
|
|
140666
|
+
}
|
|
140667
|
+
const hookResumeCapabilitiesAreFresh = suppliedToken || hookFreshlyLookedUp;
|
|
140668
|
+
const info = await resolveHookResumeInfo(hook);
|
|
140669
|
+
const { resumeContext } = info;
|
|
140670
|
+
span?.setAttributes({
|
|
140671
|
+
...HookToken(hook.token),
|
|
140672
|
+
...HookId(hook.hookId),
|
|
140673
|
+
...WorkflowRunId(hook.runId),
|
|
140674
|
+
"workflow.hook.resume_context_source": info.source
|
|
140675
|
+
});
|
|
140676
|
+
if (info.run && isTerminalWorkflowRunStatus(info.run.status)) {
|
|
140677
|
+
throw new HookNotFoundError(hook.token);
|
|
140678
|
+
}
|
|
140679
|
+
const capabilities = getRunCapabilities(resumeContext.workflowCoreVersion);
|
|
140680
|
+
let payloadKey;
|
|
140681
|
+
const runPublicKey = encryptionKeyOverride ? (
|
|
140682
|
+
// hydrate hook metadata), so sealing would add an ECDH for no
|
|
140683
|
+
// saved round trip. Reuse what it resolved.
|
|
140684
|
+
void 0
|
|
140685
|
+
) : decodeRunPublicKey(resumeContext.encryptionPublicKey);
|
|
140686
|
+
if (runPublicKey) {
|
|
140687
|
+
payloadKey = sealTo(runPublicKey);
|
|
140688
|
+
} else {
|
|
140689
|
+
let encryptionKey = encryptionKeyOverride ?? await resolveHookEncryptionKey(hook, info);
|
|
140690
|
+
if (!capabilities.supportedFormats.has(SerializationFormat.ENCRYPTED)) {
|
|
140691
|
+
encryptionKey = void 0;
|
|
140692
|
+
}
|
|
140693
|
+
payloadKey = encryptionKey;
|
|
140694
|
+
}
|
|
140695
|
+
const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION && capabilities.supportedFormats.has(SerializationFormat.GZIP);
|
|
140696
|
+
const ops = [];
|
|
140697
|
+
const readbackOps = [];
|
|
140698
|
+
const v1Compat = isLegacySpecVersion(hook.specVersion);
|
|
140699
|
+
const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
|
|
140700
|
+
await Promise.all(ops.map((op) => op.catch((error612) => {
|
|
140701
|
+
if (error612 !== void 0) throw error612;
|
|
140702
|
+
})));
|
|
140703
|
+
safeWaitUntil(Promise.all(readbackOps), (err) => {
|
|
140704
|
+
if (err === void 0) return;
|
|
140705
|
+
runtimeLogger.warn("Background readback of hook payload failed", {
|
|
140706
|
+
workflowRunId: hook.runId,
|
|
140707
|
+
hookId: hook.hookId,
|
|
140708
|
+
error: err instanceof Error ? err.message : String(err)
|
|
140709
|
+
});
|
|
140710
|
+
});
|
|
140711
|
+
if (world.capabilities?.invoke === true && !v1Compat && dehydratedPayload instanceof Uint8Array) {
|
|
140712
|
+
if (!world.invoke) {
|
|
140713
|
+
throw new WorkflowRuntimeError("World advertises invoke without implementing it");
|
|
140714
|
+
}
|
|
140715
|
+
span?.setAttributes({
|
|
140716
|
+
"workflow.hook.resume_strategy": "invoke"
|
|
140717
|
+
});
|
|
140718
|
+
const result2 = HookInvocationResultSchema.parse(await world.invoke(hook.runId, {
|
|
140719
|
+
type: "hook_resume",
|
|
140720
|
+
version: 1,
|
|
140721
|
+
hookId: hook.hookId,
|
|
140722
|
+
token: hook.token,
|
|
140723
|
+
payload: dehydratedPayload
|
|
140724
|
+
}, {
|
|
140725
|
+
idempotencyKey: logicalResumeId
|
|
140726
|
+
}));
|
|
140727
|
+
if (result2.status === "rejected") {
|
|
140728
|
+
if (result2.code === "HOOK_NOT_FOUND") throw new HookNotFoundError(hook.token);
|
|
140729
|
+
throw new WorkflowRuntimeError("Executor rejected the hook invocation input");
|
|
140730
|
+
}
|
|
140731
|
+
span?.setAttributes(HookResumeCommitted(true));
|
|
140732
|
+
return asLazyMetadataHook(hook);
|
|
140733
|
+
}
|
|
140734
|
+
span?.setAttributes({
|
|
140735
|
+
...WorkflowName(resumeContext.workflowName)
|
|
140736
|
+
});
|
|
140737
|
+
const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
|
|
140738
|
+
if (originLink) {
|
|
140739
|
+
span?.addLink?.(originLink);
|
|
140740
|
+
}
|
|
140741
|
+
const queueName = getWorkflowQueueName(resumeContext.workflowName);
|
|
140742
|
+
const queueOptions = {
|
|
140743
|
+
deploymentId: resumeContext.deploymentId,
|
|
140744
|
+
specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY
|
|
140745
|
+
};
|
|
140746
|
+
const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION || world.capabilities?.hookResumeDedup === true;
|
|
140747
|
+
const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
|
|
140748
|
+
span?.setAttributes({
|
|
140749
|
+
"workflow.hook.resume_strategy": "sequential"
|
|
140750
|
+
});
|
|
140751
|
+
const resumeId = canClaimResume ? logicalResumeId : void 0;
|
|
140752
|
+
const payloadDigest = canClaimResume ? await computeResumePayloadDigest(dehydratedPayload) : void 0;
|
|
140753
|
+
if (resumeId) {
|
|
140754
|
+
span?.setAttributes({
|
|
140755
|
+
"workflow.hook.resume_id": resumeId
|
|
140756
|
+
});
|
|
140757
|
+
}
|
|
140758
|
+
const isHookGoneError = /* @__PURE__ */ __name2((err) => HookNotFoundError.is(err) || RunExpiredError.is(err), "isHookGoneError");
|
|
140759
|
+
try {
|
|
140760
|
+
await world.events.create(hook.runId, {
|
|
140761
|
+
eventType: "hook_received",
|
|
140762
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
140763
|
+
correlationId: hook.hookId,
|
|
140764
|
+
eventData: {
|
|
140765
|
+
...v1Compat ? {} : {
|
|
140766
|
+
token: hook.token
|
|
140767
|
+
},
|
|
140768
|
+
payload: dehydratedPayload
|
|
140769
|
+
}
|
|
140770
|
+
}, {
|
|
140771
|
+
v1Compat,
|
|
140772
|
+
...resumeId && payloadDigest ? {
|
|
140773
|
+
resumeId,
|
|
140774
|
+
resumePayloadDigest: payloadDigest
|
|
140775
|
+
} : {}
|
|
140776
|
+
});
|
|
140777
|
+
} catch (err) {
|
|
140778
|
+
if (HookForceClaimedError.is(err)) throw err;
|
|
140779
|
+
if (isHookGoneError(err)) {
|
|
140780
|
+
throw new HookNotFoundError(hook.token);
|
|
140781
|
+
}
|
|
140782
|
+
throw err;
|
|
140783
|
+
}
|
|
140784
|
+
span?.setAttributes(HookResumeCommitted(true));
|
|
140785
|
+
const queuePublishRequestedAtMs = Date.now();
|
|
140786
|
+
await publishHookWakeWithRetry(() => world.queue(queueName, {
|
|
140787
|
+
runId: hook.runId,
|
|
140788
|
+
traceCarrier: resumeContext.traceCarrier ?? void 0,
|
|
140789
|
+
hookResumeTiming: {
|
|
140790
|
+
resumeRequestedAtMs,
|
|
140791
|
+
queuePublishRequestedAtMs,
|
|
140792
|
+
strategy: "sequential"
|
|
140793
|
+
}
|
|
140794
|
+
}, {
|
|
140795
|
+
...queueOptions,
|
|
140796
|
+
// Dedup retried publishes whose response was lost: a
|
|
140797
|
+
// duplicate wake is harmless for correctness (deterministic
|
|
140798
|
+
// replay) but costs a full replay of the run, and the queue
|
|
140799
|
+
// accepts a repeated idempotency key by delivering only one
|
|
140800
|
+
// of the messages. Claim-less writes have no resumeId and
|
|
140801
|
+
// keep the previous behavior.
|
|
140802
|
+
...resumeId ? {
|
|
140803
|
+
idempotencyKey: `hook-${resumeId}`
|
|
140804
|
+
} : {}
|
|
140805
|
+
}), world.isDeploymentUnavailableError?.bind(world));
|
|
140806
|
+
span?.setAttributes(HookWakePublished(true));
|
|
140807
|
+
return asLazyMetadataHook(hook);
|
|
140808
|
+
} catch (err) {
|
|
140809
|
+
span?.setAttributes({
|
|
140810
|
+
...HookToken(typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token),
|
|
140811
|
+
...HookFound(false)
|
|
140812
|
+
});
|
|
140813
|
+
throw err;
|
|
140814
|
+
}
|
|
140815
|
+
}
|
|
140816
|
+
__name(resumeHookAttempt, "resumeHookAttempt");
|
|
139884
140817
|
async function resumeWebhook(token, request) {
|
|
139885
140818
|
const resumeRequestedAtMs = Date.now();
|
|
139886
140819
|
const world = await getWorldLazy();
|
|
@@ -139908,7 +140841,7 @@ async function resumeWebhook(token, request) {
|
|
|
139908
140841
|
status: 202
|
|
139909
140842
|
});
|
|
139910
140843
|
}
|
|
139911
|
-
await resumeHookImpl(hook, request, metadataEncryptionKey(), true, resumeRequestedAtMs);
|
|
140844
|
+
await resumeHookImpl(hook, request, metadataEncryptionKey(), true, resumeRequestedAtMs, true);
|
|
139912
140845
|
if (responseReadable) {
|
|
139913
140846
|
const reader = responseReadable.getReader();
|
|
139914
140847
|
const chunk = await reader.read();
|
|
@@ -139926,7 +140859,8 @@ async function resumeWebhook(token, request) {
|
|
|
139926
140859
|
}
|
|
139927
140860
|
__name(resumeWebhook, "resumeWebhook");
|
|
139928
140861
|
var generateResumeId;
|
|
139929
|
-
var
|
|
140862
|
+
var MAX_FORCE_CLAIM_REDIRECTS;
|
|
140863
|
+
var notFoundReasons;
|
|
139930
140864
|
var init_resume_hook = __esm2({
|
|
139931
140865
|
"../core/dist/runtime/resume-hook.js"() {
|
|
139932
140866
|
"use strict";
|
|
@@ -139944,16 +140878,11 @@ var init_resume_hook = __esm2({
|
|
|
139944
140878
|
init_telemetry();
|
|
139945
140879
|
init_get_world_lazy();
|
|
139946
140880
|
init_helpers();
|
|
140881
|
+
init_hook_wake();
|
|
139947
140882
|
init_invocations();
|
|
139948
140883
|
init_wait_until();
|
|
139949
140884
|
generateResumeId = monotonicFactory();
|
|
139950
140885
|
__name2(computeResumePayloadDigest, "computeResumePayloadDigest");
|
|
139951
|
-
HOOK_WAKE_RETRY_DELAYS_MS = [
|
|
139952
|
-
25,
|
|
139953
|
-
100
|
|
139954
|
-
];
|
|
139955
|
-
__name2(isRetryableWakeError, "isRetryableWakeError");
|
|
139956
|
-
__name2(publishHookWakeWithRetry, "publishHookWakeWithRetry");
|
|
139957
140886
|
__name2(resumeContextFromRun, "resumeContextFromRun");
|
|
139958
140887
|
__name2(resolveHookResumeInfo, "resolveHookResumeInfo");
|
|
139959
140888
|
__name2(resolveHookEncryptionKey, "resolveHookEncryptionKey");
|
|
@@ -139962,7 +140891,10 @@ var init_resume_hook = __esm2({
|
|
|
139962
140891
|
__name2(asLazyMetadataHook, "asLazyMetadataHook");
|
|
139963
140892
|
__name2(getHookByToken, "getHookByToken");
|
|
139964
140893
|
__name2(resumeHook, "resumeHook");
|
|
140894
|
+
MAX_FORCE_CLAIM_REDIRECTS = 3;
|
|
140895
|
+
notFoundReasons = /* @__PURE__ */ new WeakMap();
|
|
139965
140896
|
__name2(resumeHookImpl, "resumeHookImpl");
|
|
140897
|
+
__name2(resumeHookAttempt, "resumeHookAttempt");
|
|
139966
140898
|
__name2(resumeWebhook, "resumeWebhook");
|
|
139967
140899
|
}
|
|
139968
140900
|
});
|
|
@@ -142401,7 +143333,7 @@ __name2(start, "start");
|
|
|
142401
143333
|
value: "start",
|
|
142402
143334
|
configurable: true
|
|
142403
143335
|
});
|
|
142404
|
-
})(start, "step//@workflow/core/runtime/start@5.0.0-beta.
|
|
143336
|
+
})(start, "step//@workflow/core/runtime/start@5.0.0-beta.56//start");
|
|
142405
143337
|
async function wakeUpRun(world, runId, options) {
|
|
142406
143338
|
try {
|
|
142407
143339
|
const run22 = await world.runs.get(runId, {
|
|
@@ -142876,7 +143808,7 @@ var Run = class _Run {
|
|
|
142876
143808
|
value: "wakeUp",
|
|
142877
143809
|
configurable: true
|
|
142878
143810
|
});
|
|
142879
|
-
})(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143811
|
+
})(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#wakeUp");
|
|
142880
143812
|
(function(__wf_fn, __wf_id) {
|
|
142881
143813
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142882
143814
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142885,7 +143817,7 @@ var Run = class _Run {
|
|
|
142885
143817
|
value: "cancel",
|
|
142886
143818
|
configurable: true
|
|
142887
143819
|
});
|
|
142888
|
-
})(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143820
|
+
})(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#cancel");
|
|
142889
143821
|
(function(__wf_fn, __wf_id) {
|
|
142890
143822
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142891
143823
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142894,7 +143826,7 @@ var Run = class _Run {
|
|
|
142894
143826
|
value: "getReadable",
|
|
142895
143827
|
configurable: true
|
|
142896
143828
|
});
|
|
142897
|
-
})(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143829
|
+
})(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#getReadable");
|
|
142898
143830
|
(function(__wf_fn, __wf_id) {
|
|
142899
143831
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142900
143832
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142903,7 +143835,7 @@ var Run = class _Run {
|
|
|
142903
143835
|
value: "getWritable",
|
|
142904
143836
|
configurable: true
|
|
142905
143837
|
});
|
|
142906
|
-
})(Run.prototype["getWritable"], "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143838
|
+
})(Run.prototype["getWritable"], "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#getWritable");
|
|
142907
143839
|
(function(__wf_fn, __wf_id) {
|
|
142908
143840
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142909
143841
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142912,7 +143844,7 @@ var Run = class _Run {
|
|
|
142912
143844
|
value: "exists",
|
|
142913
143845
|
configurable: true
|
|
142914
143846
|
});
|
|
142915
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143847
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#exists");
|
|
142916
143848
|
(function(__wf_fn, __wf_id) {
|
|
142917
143849
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142918
143850
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142921,7 +143853,7 @@ var Run = class _Run {
|
|
|
142921
143853
|
value: "status",
|
|
142922
143854
|
configurable: true
|
|
142923
143855
|
});
|
|
142924
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143856
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#status");
|
|
142925
143857
|
(function(__wf_fn, __wf_id) {
|
|
142926
143858
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142927
143859
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142930,7 +143862,7 @@ var Run = class _Run {
|
|
|
142930
143862
|
value: "returnValue",
|
|
142931
143863
|
configurable: true
|
|
142932
143864
|
});
|
|
142933
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143865
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#returnValue");
|
|
142934
143866
|
(function(__wf_fn, __wf_id) {
|
|
142935
143867
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142936
143868
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142939,7 +143871,7 @@ var Run = class _Run {
|
|
|
142939
143871
|
value: "workflowName",
|
|
142940
143872
|
configurable: true
|
|
142941
143873
|
});
|
|
142942
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143874
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#workflowName");
|
|
142943
143875
|
(function(__wf_fn, __wf_id) {
|
|
142944
143876
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142945
143877
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142948,7 +143880,7 @@ var Run = class _Run {
|
|
|
142948
143880
|
value: "createdAt",
|
|
142949
143881
|
configurable: true
|
|
142950
143882
|
});
|
|
142951
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143883
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#createdAt");
|
|
142952
143884
|
(function(__wf_fn, __wf_id) {
|
|
142953
143885
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142954
143886
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142957,7 +143889,7 @@ var Run = class _Run {
|
|
|
142957
143889
|
value: "startedAt",
|
|
142958
143890
|
configurable: true
|
|
142959
143891
|
});
|
|
142960
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143892
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#startedAt");
|
|
142961
143893
|
(function(__wf_fn, __wf_id) {
|
|
142962
143894
|
var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142963
143895
|
__wf_reg.set(__wf_id, __wf_fn);
|
|
@@ -142966,7 +143898,7 @@ var Run = class _Run {
|
|
|
142966
143898
|
value: "completedAt",
|
|
142967
143899
|
configurable: true
|
|
142968
143900
|
});
|
|
142969
|
-
})(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.
|
|
143901
|
+
})(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.56//Run#completedAt");
|
|
142970
143902
|
(function(__wf_cls, __wf_id) {
|
|
142971
143903
|
var __wf_sym = /* @__PURE__ */ Symbol.for("workflow-class-registry"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
|
|
142972
143904
|
__wf_reg.set(__wf_id, __wf_cls);
|
|
@@ -142976,7 +143908,7 @@ var Run = class _Run {
|
|
|
142976
143908
|
enumerable: false,
|
|
142977
143909
|
configurable: false
|
|
142978
143910
|
});
|
|
142979
|
-
})(Run, "class//@workflow/core/runtime/run@5.0.0-beta.
|
|
143911
|
+
})(Run, "class//@workflow/core/runtime/run@5.0.0-beta.56//Run");
|
|
142980
143912
|
async function fetch2(...args) {
|
|
142981
143913
|
return globalThis.fetch(...args);
|
|
142982
143914
|
}
|
|
@@ -143816,6 +144748,60 @@ __name(guardDeploymentAffinity, "guardDeploymentAffinity");
|
|
|
143816
144748
|
init_helpers3();
|
|
143817
144749
|
init_invocations2();
|
|
143818
144750
|
init_lifecycle_hooks();
|
|
144751
|
+
|
|
144752
|
+
// ../core/dist/runtime/open-hook-wait-state.js
|
|
144753
|
+
function openHookAndWaitState(events) {
|
|
144754
|
+
const hooks = /* @__PURE__ */ new Set();
|
|
144755
|
+
const waits = /* @__PURE__ */ new Map();
|
|
144756
|
+
for (const event of events) {
|
|
144757
|
+
switch (event.eventType) {
|
|
144758
|
+
case "hook_created":
|
|
144759
|
+
hooks.add(event.correlationId);
|
|
144760
|
+
break;
|
|
144761
|
+
case "hook_disposed":
|
|
144762
|
+
hooks.delete(event.correlationId);
|
|
144763
|
+
break;
|
|
144764
|
+
case "wait_created":
|
|
144765
|
+
waits.set(event.correlationId, resumeAtMs(event.eventData?.resumeAt));
|
|
144766
|
+
break;
|
|
144767
|
+
case "wait_completed":
|
|
144768
|
+
waits.delete(event.correlationId);
|
|
144769
|
+
break;
|
|
144770
|
+
}
|
|
144771
|
+
}
|
|
144772
|
+
let earliestOpenWaitResumeAtMs;
|
|
144773
|
+
for (const at of waits.values()) {
|
|
144774
|
+
if (earliestOpenWaitResumeAtMs === void 0 || at < earliestOpenWaitResumeAtMs) {
|
|
144775
|
+
earliestOpenWaitResumeAtMs = at;
|
|
144776
|
+
}
|
|
144777
|
+
}
|
|
144778
|
+
return {
|
|
144779
|
+
openHook: hooks.size > 0,
|
|
144780
|
+
openWait: waits.size > 0,
|
|
144781
|
+
earliestOpenWaitResumeAtMs
|
|
144782
|
+
};
|
|
144783
|
+
}
|
|
144784
|
+
__name(openHookAndWaitState, "openHookAndWaitState");
|
|
144785
|
+
function resumeAtMs(resumeAt) {
|
|
144786
|
+
let ms3;
|
|
144787
|
+
if (resumeAt instanceof Date) {
|
|
144788
|
+
ms3 = resumeAt.getTime();
|
|
144789
|
+
} else if (typeof resumeAt === "number") {
|
|
144790
|
+
ms3 = resumeAt;
|
|
144791
|
+
} else if (typeof resumeAt === "string") {
|
|
144792
|
+
ms3 = new Date(resumeAt).getTime();
|
|
144793
|
+
} else {
|
|
144794
|
+
return -Infinity;
|
|
144795
|
+
}
|
|
144796
|
+
return Number.isFinite(ms3) ? ms3 : -Infinity;
|
|
144797
|
+
}
|
|
144798
|
+
__name(resumeAtMs, "resumeAtMs");
|
|
144799
|
+
function hasOpenWaitDueBy(state, deadlineMs) {
|
|
144800
|
+
return state.earliestOpenWaitResumeAtMs !== void 0 && state.earliestOpenWaitResumeAtMs <= deadlineMs;
|
|
144801
|
+
}
|
|
144802
|
+
__name(hasOpenWaitDueBy, "hasOpenWaitDueBy");
|
|
144803
|
+
|
|
144804
|
+
// ../core/dist/runtime.js
|
|
143819
144805
|
init_replay_budget();
|
|
143820
144806
|
init_replay_recovery_reporter();
|
|
143821
144807
|
init_resume_latency();
|
|
@@ -143879,9 +144865,10 @@ init_util5();
|
|
|
143879
144865
|
init_compute_instance();
|
|
143880
144866
|
init_constants3();
|
|
143881
144867
|
init_helpers3();
|
|
144868
|
+
init_hook_wake2();
|
|
143882
144869
|
init_replay_recovery_reporter();
|
|
143883
144870
|
init_unserializable_step();
|
|
143884
|
-
async function createHookEvent({ runId, hookEvent, queueItem, requestId, sinceCursor, createEvent }) {
|
|
144871
|
+
async function createHookEvent({ runId, hookEvent, queueItem, requestId, sinceCursor, createEvent, world }) {
|
|
143885
144872
|
try {
|
|
143886
144873
|
const result2 = await createEvent(hookEvent, {
|
|
143887
144874
|
requestId,
|
|
@@ -143893,6 +144880,15 @@ async function createHookEvent({ runId, hookEvent, queueItem, requestId, sinceCu
|
|
|
143893
144880
|
hasAwaitedHookCreation: false
|
|
143894
144881
|
};
|
|
143895
144882
|
}
|
|
144883
|
+
if (result2.hook?.claimedFrom) {
|
|
144884
|
+
const outcome = await publishForceClaimVictimWake(world, runId, result2.hook);
|
|
144885
|
+
runtimeLogger2.info("Hook token force-claimed from another run", {
|
|
144886
|
+
workflowRunId: runId,
|
|
144887
|
+
hookId: queueItem.correlationId,
|
|
144888
|
+
victimRunId: result2.hook.claimedFrom.runId,
|
|
144889
|
+
victimWake: outcome
|
|
144890
|
+
});
|
|
144891
|
+
}
|
|
143896
144892
|
return {
|
|
143897
144893
|
hasHookConflict: false,
|
|
143898
144894
|
hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true
|
|
@@ -143929,6 +144925,7 @@ async function createHookEvent({ runId, hookEvent, queueItem, requestId, sinceCu
|
|
|
143929
144925
|
__name(createHookEvent, "createHookEvent");
|
|
143930
144926
|
async function handleSuspension({ suspension, world, run: run3, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, stepDispatch, ownerMessageId, allowDeferredBatchWork }) {
|
|
143931
144927
|
const runId = run3.runId;
|
|
144928
|
+
await republishOwedForceClaimVictimWake(world, runId, eventLog?.events);
|
|
143932
144929
|
const ensureRunReady = /* @__PURE__ */ __name(async () => {
|
|
143933
144930
|
if (runReadyBarrier) {
|
|
143934
144931
|
try {
|
|
@@ -144059,7 +145056,7 @@ async function handleSuspension({ suspension, world, run: run3, span, requestId,
|
|
|
144059
145056
|
if (hookItemsByToken.size > 0) {
|
|
144060
145057
|
const hookPhaseStart = Date.now();
|
|
144061
145058
|
await ensureRunReady();
|
|
144062
|
-
|
|
145059
|
+
const processHookGroup = /* @__PURE__ */ __name(async (items) => {
|
|
144063
145060
|
for (const queueItem of items) {
|
|
144064
145061
|
let creationConflicted = false;
|
|
144065
145062
|
if (!queueItem.hasCreatedEvent) {
|
|
@@ -144076,7 +145073,8 @@ async function handleSuspension({ suspension, world, run: run3, span, requestId,
|
|
|
144076
145073
|
tokenRetentionUntil: queueItem.tokenRetentionUntil,
|
|
144077
145074
|
metadata: hookMetadata,
|
|
144078
145075
|
isWebhook: queueItem.isWebhook ?? false,
|
|
144079
|
-
...queueItem.isSystem && { isSystem: true }
|
|
145076
|
+
...queueItem.isSystem && { isSystem: true },
|
|
145077
|
+
...queueItem.force && { force: true }
|
|
144080
145078
|
}
|
|
144081
145079
|
};
|
|
144082
145080
|
const result2 = await createHookEvent({
|
|
@@ -144085,7 +145083,8 @@ async function handleSuspension({ suspension, world, run: run3, span, requestId,
|
|
|
144085
145083
|
queueItem,
|
|
144086
145084
|
requestId,
|
|
144087
145085
|
sinceCursor: hookDeltaCursor,
|
|
144088
|
-
createEvent: createGuarded
|
|
145086
|
+
createEvent: createGuarded,
|
|
145087
|
+
world
|
|
144089
145088
|
});
|
|
144090
145089
|
if (result2.hasHookConflict) {
|
|
144091
145090
|
hookConflictCorrelationIds.push(queueItem.correlationId);
|
|
@@ -144099,7 +145098,13 @@ async function handleSuspension({ suspension, world, run: run3, span, requestId,
|
|
|
144099
145098
|
await disposeHook(queueItem);
|
|
144100
145099
|
}
|
|
144101
145100
|
}
|
|
144102
|
-
})
|
|
145101
|
+
}, "processHookGroup");
|
|
145102
|
+
const groups = [...hookItemsByToken.values()];
|
|
145103
|
+
const holdsForcedCreation = /* @__PURE__ */ __name((items) => items.some((item) => item.force === true && !item.hasCreatedEvent), "holdsForcedCreation");
|
|
145104
|
+
for (const items of groups.filter(holdsForcedCreation)) {
|
|
145105
|
+
await settlePhase([processHookGroup(items)]);
|
|
145106
|
+
}
|
|
145107
|
+
await settlePhase(groups.filter((items) => !holdsForcedCreation(items)).map(processHookGroup));
|
|
144103
145108
|
hookCreationMs = Date.now() - hookPhaseStart;
|
|
144104
145109
|
}
|
|
144105
145110
|
const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
|
|
@@ -144693,13 +145698,14 @@ async function handleSuspension({ suspension, world, run: run3, span, requestId,
|
|
|
144693
145698
|
const now2 = Date.now();
|
|
144694
145699
|
let soonestWait;
|
|
144695
145700
|
for (const queueItem of waitItems) {
|
|
144696
|
-
const
|
|
144697
|
-
const delayMs = Math.max(1e3,
|
|
145701
|
+
const resumeAtMs2 = queueItem.resumeAt.getTime();
|
|
145702
|
+
const delayMs = Math.max(1e3, resumeAtMs2 - now2);
|
|
144698
145703
|
const timeoutSeconds = Math.ceil(delayMs / 1e3);
|
|
144699
145704
|
if (!soonestWait || timeoutSeconds < soonestWait.seconds) {
|
|
144700
145705
|
soonestWait = {
|
|
144701
145706
|
seconds: timeoutSeconds,
|
|
144702
|
-
correlationId: queueItem.correlationId
|
|
145707
|
+
correlationId: queueItem.correlationId,
|
|
145708
|
+
resumeAtMs: resumeAtMs2
|
|
144703
145709
|
};
|
|
144704
145710
|
}
|
|
144705
145711
|
}
|
|
@@ -145694,6 +146700,17 @@ function createCreateHook(ctx) {
|
|
|
145694
146700
|
if (options.experimental_minRetention !== void 0 && ctx.worldCapabilities?.hookRetention?.active !== true) {
|
|
145695
146701
|
throw new FatalError2("The configured World does not support `experimental_minRetention` for Hooks.");
|
|
145696
146702
|
}
|
|
146703
|
+
if (options.experimental_force === true) {
|
|
146704
|
+
if (options.token === void 0 || options.token === null) {
|
|
146705
|
+
throw new Error("`createHook()` was called with `experimental_force: true` but no `token`. Force-claiming only applies to an explicit token another run may hold.");
|
|
146706
|
+
}
|
|
146707
|
+
if (options.isWebhook === true) {
|
|
146708
|
+
throw new Error("Webhook hooks do not support `experimental_force`. Use a non-webhook `createHook()` with an explicit token.");
|
|
146709
|
+
}
|
|
146710
|
+
if (ctx.worldCapabilities?.hookForceClaim !== true) {
|
|
146711
|
+
throw new FatalError2("The configured World does not support `experimental_force` for Hooks.");
|
|
146712
|
+
}
|
|
146713
|
+
}
|
|
145697
146714
|
const correlationId = `hook_${ctx.generateUlid()}`;
|
|
145698
146715
|
const token = options.token ?? ctx.generateNanoid();
|
|
145699
146716
|
const tokenRetentionUntil = options.experimental_minRetention === void 0 ? void 0 : parseDurationToDate2(options.experimental_minRetention);
|
|
@@ -145703,6 +146720,7 @@ function createCreateHook(ctx) {
|
|
|
145703
146720
|
correlationId,
|
|
145704
146721
|
token,
|
|
145705
146722
|
tokenRetentionUntil,
|
|
146723
|
+
...options.experimental_force === true && { force: true },
|
|
145706
146724
|
metadata: options.metadata,
|
|
145707
146725
|
isWebhook
|
|
145708
146726
|
});
|
|
@@ -145714,6 +146732,7 @@ function createCreateHook(ctx) {
|
|
|
145714
146732
|
let hasDisposedEvent = false;
|
|
145715
146733
|
let hasConflict = false;
|
|
145716
146734
|
let conflictErrorRef = null;
|
|
146735
|
+
let forceClaimedErrorRef = null;
|
|
145717
146736
|
let conflictRunRef = null;
|
|
145718
146737
|
let registrationDelivered = Promise.resolve();
|
|
145719
146738
|
function deliverRegistration(deliveredAt, settle) {
|
|
@@ -145774,10 +146793,11 @@ function createCreateHook(ctx) {
|
|
|
145774
146793
|
if (event.eventType === "hook_conflict") {
|
|
145775
146794
|
ctx.invocationsQueue.delete(correlationId);
|
|
145776
146795
|
const conflictEvent = event;
|
|
145777
|
-
const
|
|
146796
|
+
const forced = options.experimental_force === true && conflictEvent.eventData.forceRefusedReason === void 0;
|
|
146797
|
+
const conflictError = forced ? new FatalError2(`createHook({ experimental_force: true }) for token "${conflictEvent.eventData.token}" was answered with a hook_conflict: the configured World does not support force-claiming hook tokens${conflictEvent.eventData.conflictingRunId ? ` (run "${conflictEvent.eventData.conflictingRunId}" holds it)` : ""}.`) : new HookConflictError2(conflictEvent.eventData.token, conflictEvent.eventData.conflictingRunId);
|
|
145778
146798
|
hasConflict = true;
|
|
145779
146799
|
conflictErrorRef = conflictError;
|
|
145780
|
-
conflictRunRef = createConflictingRun(ctx, conflictEvent.eventData.conflictingRunId);
|
|
146800
|
+
conflictRunRef = forced ? null : createConflictingRun(ctx, conflictEvent.eventData.conflictingRunId);
|
|
145781
146801
|
const pendingPromises = promises.slice();
|
|
145782
146802
|
promises.length = 0;
|
|
145783
146803
|
const pendingGetConflictPromises = getConflictPromises.slice();
|
|
@@ -145869,6 +146889,28 @@ function createCreateHook(ctx) {
|
|
|
145869
146889
|
if (event.eventType === "hook_disposed") {
|
|
145870
146890
|
ctx.invocationsQueue.delete(correlationId);
|
|
145871
146891
|
hasDisposedEvent = true;
|
|
146892
|
+
const claimedBy = event.eventData?.forceClaimedBy;
|
|
146893
|
+
if (claimedBy) {
|
|
146894
|
+
const error121 = new HookForceClaimedError2(token, claimedBy.runId, claimedBy.hookId);
|
|
146895
|
+
forceClaimedErrorRef = error121;
|
|
146896
|
+
const pendingPromises = promises.slice();
|
|
146897
|
+
promises.length = 0;
|
|
146898
|
+
const pendingGetConflictPromises = getConflictPromises.slice();
|
|
146899
|
+
getConflictPromises.length = 0;
|
|
146900
|
+
ctx.promiseQueue = ctx.promiseQueue.then(() => {
|
|
146901
|
+
for (const resolver2 of pendingPromises) {
|
|
146902
|
+
resolver2.reject(error121);
|
|
146903
|
+
}
|
|
146904
|
+
for (const resolver2 of pendingGetConflictPromises) {
|
|
146905
|
+
resolver2.resolve(null);
|
|
146906
|
+
}
|
|
146907
|
+
});
|
|
146908
|
+
webhookLogger2.debug("Hook force-claimed by another run", {
|
|
146909
|
+
correlationId,
|
|
146910
|
+
token,
|
|
146911
|
+
claimedByRunId: claimedBy.runId
|
|
146912
|
+
});
|
|
146913
|
+
}
|
|
145872
146914
|
return EventConsumerResult2.Finished;
|
|
145873
146915
|
}
|
|
145874
146916
|
ctx.promiseQueue = ctx.promiseQueue.then(() => {
|
|
@@ -145891,6 +146933,13 @@ function createCreateHook(ctx) {
|
|
|
145891
146933
|
return nextDelivery.claim();
|
|
145892
146934
|
}
|
|
145893
146935
|
}
|
|
146936
|
+
if (forceClaimedErrorRef) {
|
|
146937
|
+
const error121 = forceClaimedErrorRef;
|
|
146938
|
+
ctx.promiseQueue = ctx.promiseQueue.then(() => {
|
|
146939
|
+
resolvers.reject(error121);
|
|
146940
|
+
});
|
|
146941
|
+
return resolvers.promise;
|
|
146942
|
+
}
|
|
145894
146943
|
if (eventLogEmpty) {
|
|
145895
146944
|
scheduleWorkflowSuspension(ctx);
|
|
145896
146945
|
}
|
|
@@ -146917,28 +147966,6 @@ function countMissingIds(ids, present) {
|
|
|
146917
147966
|
return missing;
|
|
146918
147967
|
}
|
|
146919
147968
|
__name(countMissingIds, "countMissingIds");
|
|
146920
|
-
function openHookAndWaitState(events) {
|
|
146921
|
-
const hooks = /* @__PURE__ */ new Set();
|
|
146922
|
-
const waits = /* @__PURE__ */ new Set();
|
|
146923
|
-
for (const event of events) {
|
|
146924
|
-
switch (event.eventType) {
|
|
146925
|
-
case "hook_created":
|
|
146926
|
-
hooks.add(event.correlationId);
|
|
146927
|
-
break;
|
|
146928
|
-
case "hook_disposed":
|
|
146929
|
-
hooks.delete(event.correlationId);
|
|
146930
|
-
break;
|
|
146931
|
-
case "wait_created":
|
|
146932
|
-
waits.add(event.correlationId);
|
|
146933
|
-
break;
|
|
146934
|
-
case "wait_completed":
|
|
146935
|
-
waits.delete(event.correlationId);
|
|
146936
|
-
break;
|
|
146937
|
-
}
|
|
146938
|
-
}
|
|
146939
|
-
return { openHook: hooks.size > 0, openWait: waits.size > 0 };
|
|
146940
|
-
}
|
|
146941
|
-
__name(openHookAndWaitState, "openHookAndWaitState");
|
|
146942
147969
|
function getRetentionDecision({ suspension, serializationBlockerCount, hookContinuation = false, invocationContinuation = false }) {
|
|
146943
147970
|
if (!isVmRetentionEnabled()) {
|
|
146944
147971
|
return { retain: false, reason: "disabled" };
|
|
@@ -147104,6 +148131,8 @@ function workflowEntrypoint(workflowCode2, options) {
|
|
|
147104
148131
|
});
|
|
147105
148132
|
const invocationStartTime = Date.now();
|
|
147106
148133
|
const noInlineReplayAfterMs = await getMaxInlineDurationMs(world, invocationStartTime);
|
|
148134
|
+
const openWaitDueDeadlineMs = invocationStartTime + noInlineReplayAfterMs + getOpenWaitClockSkewMs();
|
|
148135
|
+
let eventLogFromInlineDelta = false;
|
|
147107
148136
|
let loopIteration = 0;
|
|
147108
148137
|
const replayRecoveryReporter = replayDivergence ? new ReplayRecoveryReporter(replayDivergence.count) : ReplayRecoveryReporter.inert();
|
|
147109
148138
|
let compiledWorkflowScripts;
|
|
@@ -147982,6 +149011,7 @@ function workflowEntrypoint(workflowCode2, options) {
|
|
|
147982
149011
|
return;
|
|
147983
149012
|
}
|
|
147984
149013
|
if (eventLog.type !== "ready") {
|
|
149014
|
+
eventLogFromInlineDelta = false;
|
|
147985
149015
|
const page = await loadWorkflowRunEvents(runId, eventLog.type === "loadAfter" ? eventLog.cursor : void 0);
|
|
147986
149016
|
if (eventLog.type === "loadAfter") {
|
|
147987
149017
|
appendEventLog(eventLog, page);
|
|
@@ -148029,6 +149059,7 @@ function workflowEntrypoint(workflowCode2, options) {
|
|
|
148029
149059
|
const completedWaitIdsAfterWrites = new Set(eventLog.events.filter((e) => e.eventType === "wait_completed").map((e) => e.correlationId));
|
|
148030
149060
|
const missingWaitCompletions = waitsToComplete.filter((waitEvent) => !completedWaitIdsAfterWrites.has(waitEvent.correlationId));
|
|
148031
149061
|
if (missingWaitCompletions.length > 0) {
|
|
149062
|
+
eventLogFromInlineDelta = false;
|
|
148032
149063
|
if (eventLog.cursor) {
|
|
148033
149064
|
const page = await loadWorkflowRunEvents(runId, eventLog.cursor);
|
|
148034
149065
|
const completedWaitIdsAfterCursor = new Set(page.events.filter((e) => e.eventType === "wait_completed").map((e) => e.correlationId));
|
|
@@ -148329,6 +149360,18 @@ function workflowEntrypoint(workflowCode2, options) {
|
|
|
148329
149360
|
continue;
|
|
148330
149361
|
}
|
|
148331
149362
|
const pendingSteps = suspensionResult.pendingSteps;
|
|
149363
|
+
if (eventLogFromInlineDelta && suspensionResult.waitTimeout !== void 0 && pendingSteps.length === 0 && !suspensionResult.hasAwaitedHookCreation && openHookWait.value.openWait) {
|
|
149364
|
+
runtimeLogger2.debug("Re-reading the event log before parking on a wait over an inline delta", {
|
|
149365
|
+
workflowRunId: runId,
|
|
149366
|
+
loopIteration,
|
|
149367
|
+
waitCorrelationId: suspensionResult.waitTimeout.correlationId
|
|
149368
|
+
});
|
|
149369
|
+
span?.setAttributes({
|
|
149370
|
+
"workflow.wait_park_reread": true
|
|
149371
|
+
});
|
|
149372
|
+
eventLog = nextEventLogLoad(eventLog);
|
|
149373
|
+
continue;
|
|
149374
|
+
}
|
|
148332
149375
|
const lazyInlineSteps = suspensionResult.lazyInlineSteps;
|
|
148333
149376
|
const inlineCorrelationIds = new Set(lazyInlineSteps.map((s) => s.correlationId));
|
|
148334
149377
|
const traceCarrier = await nextTraceCarrier();
|
|
@@ -148476,7 +149519,13 @@ function workflowEntrypoint(workflowCode2, options) {
|
|
|
148476
149519
|
return;
|
|
148477
149520
|
}
|
|
148478
149521
|
const openHookWaitState = openHookWait.value;
|
|
148479
|
-
const
|
|
149522
|
+
const waitDueThisInvocation = hasOpenWaitDueBy(openHookWaitState, openWaitDueDeadlineMs) || suspensionResult.waitTimeout !== void 0 && !(suspensionResult.waitTimeout.resumeAtMs > openWaitDueDeadlineMs);
|
|
149523
|
+
const requestInlineDelta = typeof eventLog.cursor === "string" && err.stepCount === 1 && pendingSteps.length === 1 && lazyInlineSteps.length === 1 && ownedRecoverySteps.length === 0 && !waitDueThisInvocation;
|
|
149524
|
+
if (requestInlineDelta && (openHookWaitState.openWait || suspensionResult.waitTimeout !== void 0)) {
|
|
149525
|
+
span?.setAttributes({
|
|
149526
|
+
"workflow.inline_delta_over_pending_wait": true
|
|
149527
|
+
});
|
|
149528
|
+
}
|
|
148480
149529
|
const suppressOptimisticStart = openHookWaitState.openHook || err.hookCount > 0 || suspensionResult.hasHookEvents;
|
|
148481
149530
|
const forceOptimisticStart = turbo && !suspensionResult.hasAttributeEvents && !suspensionResult.waitTimeout && !suspensionResult.hasHookEvents && !suspensionResult.hasAwaitedHookCreation && !openHookWaitState.openHook && !openHookWaitState.openWait;
|
|
148482
149531
|
const latencyTracking = computeStepLatencyTracking({
|
|
@@ -148687,6 +149736,7 @@ function workflowEntrypoint(workflowCode2, options) {
|
|
|
148687
149736
|
const only = stepResults[0];
|
|
148688
149737
|
if (only.type === "completed" && only.inlineDelta) {
|
|
148689
149738
|
appendEventLog(eventLog, only.inlineDelta);
|
|
149739
|
+
eventLogFromInlineDelta = !only.inlineDelta.hasMore;
|
|
148690
149740
|
eventLog = only.inlineDelta.hasMore ? nextEventLogLoad(eventLog) : { ...eventLog, type: "ready" };
|
|
148691
149741
|
continue;
|
|
148692
149742
|
}
|
|
@@ -149436,6 +150486,7 @@ var ERROR_SLUGS = {
|
|
|
149436
150486
|
FETCH_IN_WORKFLOW_FUNCTION: "fetch-in-workflow",
|
|
149437
150487
|
TIMEOUT_FUNCTIONS_IN_WORKFLOW: "timeout-in-workflow",
|
|
149438
150488
|
HOOK_CONFLICT: "hook-conflict",
|
|
150489
|
+
HOOK_FORCE_CLAIMED: "hook-force-claimed",
|
|
149439
150490
|
CORRUPTED_EVENT_LOG: "corrupted-event-log",
|
|
149440
150491
|
REPLAY_DIVERGENCE: "replay-divergence",
|
|
149441
150492
|
STEP_NOT_REGISTERED: "step-not-registered",
|
|
@@ -149549,6 +150600,30 @@ var HookConflictError = class extends WorkflowError {
|
|
|
149549
150600
|
return isError(value) && value.name === "HookConflictError";
|
|
149550
150601
|
}
|
|
149551
150602
|
};
|
|
150603
|
+
var HookForceClaimedError = class extends WorkflowError {
|
|
150604
|
+
static {
|
|
150605
|
+
__name(this, "HookForceClaimedError");
|
|
150606
|
+
}
|
|
150607
|
+
token;
|
|
150608
|
+
/** The run that took the token. */
|
|
150609
|
+
claimedByRunId;
|
|
150610
|
+
/** The hook (in \`claimedByRunId\`) the token now belongs to. */
|
|
150611
|
+
claimedByHookId;
|
|
150612
|
+
constructor(token, claimedByRunId, claimedByHookId) {
|
|
150613
|
+
super(\`Hook token "\${token}" was force-claimed by another workflow (run "\${claimedByRunId}")\`, {
|
|
150614
|
+
slug: ERROR_SLUGS.HOOK_FORCE_CLAIMED
|
|
150615
|
+
});
|
|
150616
|
+
this.name = "HookForceClaimedError";
|
|
150617
|
+
this.token = token;
|
|
150618
|
+
this.claimedByRunId = claimedByRunId;
|
|
150619
|
+
if (claimedByHookId !== void 0) {
|
|
150620
|
+
this.claimedByHookId = claimedByHookId;
|
|
150621
|
+
}
|
|
150622
|
+
}
|
|
150623
|
+
static is(value) {
|
|
150624
|
+
return isError(value) && value.name === "HookForceClaimedError";
|
|
150625
|
+
}
|
|
150626
|
+
};
|
|
149552
150627
|
var StreamError = class extends WorkflowWorldError {
|
|
149553
150628
|
static {
|
|
149554
150629
|
__name(this, "StreamError");
|
|
@@ -149605,6 +150680,7 @@ var RetryableError = class extends Error {
|
|
|
149605
150680
|
var FATAL_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//FatalError");
|
|
149606
150681
|
var RETRYABLE_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RetryableError");
|
|
149607
150682
|
var HOOK_CONFLICT_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookConflictError");
|
|
150683
|
+
var HOOK_FORCE_CLAIMED_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError");
|
|
149608
150684
|
var RUNTIME_DECRYPTION_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RuntimeDecryptionError");
|
|
149609
150685
|
var STREAM_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//StreamError");
|
|
149610
150686
|
if (typeof globalThis !== "undefined") {
|
|
@@ -149632,6 +150708,14 @@ if (typeof globalThis !== "undefined") {
|
|
|
149632
150708
|
configurable: false
|
|
149633
150709
|
});
|
|
149634
150710
|
}
|
|
150711
|
+
if (!Object.hasOwn(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY)) {
|
|
150712
|
+
Object.defineProperty(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY, {
|
|
150713
|
+
value: HookForceClaimedError,
|
|
150714
|
+
writable: false,
|
|
150715
|
+
enumerable: false,
|
|
150716
|
+
configurable: false
|
|
150717
|
+
});
|
|
150718
|
+
}
|
|
149635
150719
|
if (!Object.hasOwn(globalThis, RUNTIME_DECRYPTION_ERROR_KEY)) {
|
|
149636
150720
|
Object.defineProperty(globalThis, RUNTIME_DECRYPTION_ERROR_KEY, {
|
|
149637
150721
|
value: RuntimeDecryptionError,
|
|
@@ -149736,11 +150820,11 @@ var Run = class _Run {
|
|
|
149736
150820
|
return this.getWritable();
|
|
149737
150821
|
}
|
|
149738
150822
|
};
|
|
149739
|
-
Run.prototype["wakeUp"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
149740
|
-
Run.prototype["cancel"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
149741
|
-
Run.prototype["getReadable"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
149742
|
-
Run.prototype["getWritable"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
149743
|
-
var __step_Run$exists = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150823
|
+
Run.prototype["wakeUp"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#wakeUp");
|
|
150824
|
+
Run.prototype["cancel"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#cancel");
|
|
150825
|
+
Run.prototype["getReadable"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#getReadable");
|
|
150826
|
+
Run.prototype["getWritable"] = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#getWritable");
|
|
150827
|
+
var __step_Run$exists = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#exists");
|
|
149744
150828
|
Object.defineProperty(Run.prototype, "exists", {
|
|
149745
150829
|
get() {
|
|
149746
150830
|
return __step_Run$exists.call(this);
|
|
@@ -149748,7 +150832,7 @@ Object.defineProperty(Run.prototype, "exists", {
|
|
|
149748
150832
|
configurable: true,
|
|
149749
150833
|
enumerable: false
|
|
149750
150834
|
});
|
|
149751
|
-
var __step_Run$status = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150835
|
+
var __step_Run$status = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#status");
|
|
149752
150836
|
Object.defineProperty(Run.prototype, "status", {
|
|
149753
150837
|
get() {
|
|
149754
150838
|
return __step_Run$status.call(this);
|
|
@@ -149756,7 +150840,7 @@ Object.defineProperty(Run.prototype, "status", {
|
|
|
149756
150840
|
configurable: true,
|
|
149757
150841
|
enumerable: false
|
|
149758
150842
|
});
|
|
149759
|
-
var __step_Run$returnValue = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150843
|
+
var __step_Run$returnValue = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#returnValue");
|
|
149760
150844
|
Object.defineProperty(Run.prototype, "returnValue", {
|
|
149761
150845
|
get() {
|
|
149762
150846
|
return __step_Run$returnValue.call(this);
|
|
@@ -149764,7 +150848,7 @@ Object.defineProperty(Run.prototype, "returnValue", {
|
|
|
149764
150848
|
configurable: true,
|
|
149765
150849
|
enumerable: false
|
|
149766
150850
|
});
|
|
149767
|
-
var __step_Run$workflowName = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150851
|
+
var __step_Run$workflowName = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#workflowName");
|
|
149768
150852
|
Object.defineProperty(Run.prototype, "workflowName", {
|
|
149769
150853
|
get() {
|
|
149770
150854
|
return __step_Run$workflowName.call(this);
|
|
@@ -149772,7 +150856,7 @@ Object.defineProperty(Run.prototype, "workflowName", {
|
|
|
149772
150856
|
configurable: true,
|
|
149773
150857
|
enumerable: false
|
|
149774
150858
|
});
|
|
149775
|
-
var __step_Run$createdAt = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150859
|
+
var __step_Run$createdAt = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#createdAt");
|
|
149776
150860
|
Object.defineProperty(Run.prototype, "createdAt", {
|
|
149777
150861
|
get() {
|
|
149778
150862
|
return __step_Run$createdAt.call(this);
|
|
@@ -149780,7 +150864,7 @@ Object.defineProperty(Run.prototype, "createdAt", {
|
|
|
149780
150864
|
configurable: true,
|
|
149781
150865
|
enumerable: false
|
|
149782
150866
|
});
|
|
149783
|
-
var __step_Run$startedAt = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150867
|
+
var __step_Run$startedAt = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#startedAt");
|
|
149784
150868
|
Object.defineProperty(Run.prototype, "startedAt", {
|
|
149785
150869
|
get() {
|
|
149786
150870
|
return __step_Run$startedAt.call(this);
|
|
@@ -149788,7 +150872,7 @@ Object.defineProperty(Run.prototype, "startedAt", {
|
|
|
149788
150872
|
configurable: true,
|
|
149789
150873
|
enumerable: false
|
|
149790
150874
|
});
|
|
149791
|
-
var __step_Run$completedAt = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.
|
|
150875
|
+
var __step_Run$completedAt = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/run@5.0.0-beta.56//Run#completedAt");
|
|
149792
150876
|
Object.defineProperty(Run.prototype, "completedAt", {
|
|
149793
150877
|
get() {
|
|
149794
150878
|
return __step_Run$completedAt.call(this);
|
|
@@ -149805,7 +150889,7 @@ Object.defineProperty(Run.prototype, "completedAt", {
|
|
|
149805
150889
|
enumerable: false,
|
|
149806
150890
|
configurable: false
|
|
149807
150891
|
});
|
|
149808
|
-
})(Run, "class//@workflow/core/runtime/run@5.0.0-beta.
|
|
150892
|
+
})(Run, "class//@workflow/core/runtime/run@5.0.0-beta.56//Run");
|
|
149809
150893
|
|
|
149810
150894
|
// ../core/dist/workflow/create-hook.js
|
|
149811
150895
|
aliasSerializationClass(RUN_CLASS_ID, Run);
|
|
@@ -157401,7 +158485,7 @@ globalThis.__private_workflows.set("workflow//./workflows/inline-execution//hook
|
|
|
157401
158485
|
var latestNoOpWarning = globalSingleton("@workflow/core//latestNoOpWarning", 1, () => ({
|
|
157402
158486
|
warned: false
|
|
157403
158487
|
}));
|
|
157404
|
-
var start = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/start@5.0.0-beta.
|
|
158488
|
+
var start = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//@workflow/core/runtime/start@5.0.0-beta.56//start");
|
|
157405
158489
|
|
|
157406
158490
|
// workflows/lineage.ts
|
|
157407
158491
|
var noop = globalThis[/* @__PURE__ */ Symbol.for("WORKFLOW_USE_STEP")]("step//./workflows/lineage//noop");
|