@effect-agent/platform-cloudflare 0.1.0-beta.131 → 0.1.0-beta.132
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Alarm.mjs +2 -1
- package/dist/Alarm.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +9 -2
package/dist/Alarm.mjs
CHANGED
|
@@ -629,7 +629,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
629
629
|
const nextAttemptAt = yield* mutations.withSnapshot((active) => runTransaction("checkpoint native maintenance", () => ctx.storage.transaction(async (transaction) => {
|
|
630
630
|
const { state } = await readMaintenanceState(transaction);
|
|
631
631
|
const mutationOverlap = observation.activeAtStart > 0 || started.activeAtStart > 0 || active > 0;
|
|
632
|
-
const
|
|
632
|
+
const generation = remaining.length === 0 && !mutationOverlap && state.dirty === started.generation ? started.generation : observation.generation;
|
|
633
|
+
const processed = autonomous || mutationOverlap ? state.processed : state.processed > generation ? state.processed : generation;
|
|
633
634
|
const canBackoff = !mutationOverlap && state.dirty === started.generation;
|
|
634
635
|
const next = ThreadMaintenanceState.make({
|
|
635
636
|
...Struct.omit(state, ["retry"]),
|
package/dist/Alarm.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Alarm.mjs","names":[],"sources":["../src/Alarm.ts"],"sourcesContent":["import {\n Cause,\n Clock,\n Context,\n DateTime,\n Deferred,\n Effect,\n Exit,\n Fiber,\n Layer,\n Option,\n Random,\n Ref,\n Result,\n Schema,\n Scope,\n Semaphore,\n Stream,\n Struct,\n} from \"effect\";\nimport { type DurableBindingFailure } from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n isolateRecovery,\n RecoveryBlocked,\n RecoveryFailure,\n type DurableWorkerFailure,\n type RecoveryReport,\n RecoverySweepResult,\n} from \"effect-agent/durable-agent-runtime\";\nimport { ThreadId, SubmissionId } from \"effect-agent/identifiers\";\nimport {\n OperationAuthorizationRequest,\n OperationAuthorizer,\n type OperationDenied,\n} from \"effect-agent/operation-authorizer\";\nimport {\n AbortIntentRequest,\n SubmissionLedger,\n type SubmissionWorkItem,\n} from \"effect-agent/submission-ledger\";\nimport {\n ThreadProjectionMaintenance,\n drainDue,\n type ThreadProjectionError,\n} from \"effect-agent/thread-projection-maintenance\";\nimport { WakeScheduler } from \"effect-agent/wake-scheduler\";\nimport { DurableObjectStorage } from \"effect-cf\";\nimport { SqlClient } from \"effect/unstable/sql/SqlClient\";\n\nimport { DurableObjectContext } from \"./CloudflareBindings.ts\";\nimport { AuxiliaryDispatchMillis, CloudflareDurableRuntimeConfig } from \"./CloudflareConfig.ts\";\nimport { safeCauseMessage } from \"./internal/boundary.ts\";\n\n/**\n * The single multiplexed Durable Object alarm (decision D-P6-2). A Durable Object has ONE\n * alarm slot; every cadence the Node host ran on fibers (wake scan, lease expiry, settlement\n * and abort re-checks, retry backoff) multiplexes into one idempotent maintenance pass, and\n * the slot always holds the EARLIEST deadline any caller asked for.\n *\n * The alarm invariant (plan §1.4): every committed actionable mutation carries a newer durable\n * maintenance generation and a committed alarm. Stable externally-driven waits may be\n * nonterminal without retaining an alarm; their resolving mutation advances the generation and\n * restores the alarm atomically.\n */\n\n/** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */\nexport class DurableAlarmError extends Schema.TaggedError<DurableAlarmError>()(\n \"DurableAlarmError\",\n {\n operation: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\nconst alarmFailure =\n (operation: string) =>\n (cause: unknown): DurableAlarmError =>\n DurableAlarmError.make({\n operation,\n message: safeCauseMessage(cause, \"The Cloudflare alarm API failed without a diagnostic\"),\n cause,\n });\n\n// SQL and raw KV/alarm operations share one physical SQLite transaction. Reserve its\n// connection for each short storage operation, never around a mutation or snapshot body.\nconst makeStorageEffect = Effect.map(\n SqlClient,\n (sql) =>\n <A, R>(operation: string, execute: Effect.Effect<A, DurableAlarmError, R>) =>\n Effect.flatMap(Effect.serviceOption(sql.transactionService), (current) => {\n const body = Effect.uninterruptible(execute);\n\n return current._tag === \"Some\"\n ? body\n : Effect.scoped(\n Effect.andThen(sql.reserve.pipe(Effect.mapError(alarmFailure(operation))), body),\n );\n }),\n);\n\nconst makeStorageOperation = Effect.map(\n makeStorageEffect,\n (run) =>\n <A>(operation: string, execute: () => Promise<A>) =>\n run(operation, Effect.tryPromise({ try: execute, catch: alarmFailure(operation) })),\n);\n\n/** `ctx.storage` alarm slot as an Effect service; storage is truth, never a memory field. */\nexport class DurableAlarmService extends Context.Service<\n DurableAlarmService,\n {\n /** The scheduled deadline in epoch milliseconds, if any. */\n readonly scheduled: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n /** Replace the slot with this deadline. */\n readonly scheduleAt: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /** Keep the EARLIER of the existing deadline and this one (the multiplexing rule). */\n readonly ensureScheduledBy: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /**\n * Arm an immediate alarm (the durable, coalescing local wake) — DEFERRED while a\n * maintenance pass is executing. Workerd cancels an in-flight alarm handler when a new\n * EARLIER deadline is written during its execution (`requestScheduledAlarm`), and the\n * maintenance pass runs INSIDE the alarm handler: an immediate wake landing mid-pass\n * (a routed port mutation, a sibling's `wake()`, the coordinator's own local notify)\n * would kill the running Attempt — manufacturing an ownership loss no real eviction\n * caused, and routing open uncertain-class Tool Calls into spurious Unknown Outcomes.\n * Deferral is contract-safe: wakes are droppable hints, every mutating entry point\n * pre-arms BEFORE its first durable mutation (the alarm invariant never rests on this\n * call). The pass's durable generation check observes any racing mutation, so the\n * in-memory hint does not need to be flushed after a stable wait is acknowledged.\n */\n readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;\n /**\n * Run one maintenance pass with wake deferral (see `scheduleNow`). Calls made while `body`\n * executes are droppable promptness hints; correctness rests on the durable generation.\n */\n readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;\n /** Clear the slot; correctness-sensitive clears live in maintenance generation transactions. */\n readonly cancel: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableAlarmService\") {\n static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext | SqlClient> =\n Layer.effect(DurableAlarmService)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n /**\n * In-memory pass bookkeeping — a pure CACHE, never state: a fresh incarnation has no\n * running pass, and a deferred wake lost to eviction was only ever a promptness hint\n * on top of the already-committed pre-armed alarm.\n */\n const runningPasses = yield* Ref.make(0);\n\n const storageOperation = yield* makeStorageOperation;\n\n const scheduled = storageOperation(\"get alarm\", () => ctx.storage.getAlarm()).pipe(\n Effect.map((deadline) =>\n deadline === null ? Option.none<number>() : Option.some(deadline),\n ),\n );\n\n const scheduleAt = (epochMillis: number) =>\n storageOperation(\"set alarm\", () => ctx.storage.setAlarm(epochMillis));\n\n const ensureScheduledBy = (epochMillis: number) =>\n storageOperation(\"ensure alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const existing = await transaction.getAlarm();\n\n if (existing === null || existing > epochMillis) {\n await transaction.setAlarm(epochMillis);\n }\n }),\n );\n\n const armNow = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => ensureScheduledBy(now)),\n );\n\n const scheduleNow = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) => (passes > 0 ? Effect.void : armNow)),\n );\n\n const withWakesDeferred = <A, E, R>(body: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Ref.update(runningPasses, (passes) => passes + 1).pipe(\n Effect.andThen(body),\n Effect.ensuring(Ref.update(runningPasses, (passes) => passes - 1)),\n );\n\n const cancel = storageOperation(\"delete alarm\", () => ctx.storage.deleteAlarm());\n\n return DurableAlarmService.of({\n scheduled,\n scheduleAt,\n ensureScheduledBy,\n scheduleNow,\n withWakesDeferred,\n cancel,\n });\n }),\n );\n}\n\n/** What one maintenance pass did — auditable evidence mirroring `NodeDurableHost`'s report. */\nexport class MaintenancePassReport extends Schema.Class<MaintenancePassReport>(\n \"@effect-agent/platform-cloudflare/MaintenancePassReport\",\n)({\n /** `caught-up` ran no runtime work (publication may be pending); `actionable` ran recovery. */\n phase: Schema.Literals([\"caught-up\", \"actionable\"]),\n /** Recovery decisions and Thread faults observed during this event. */\n recovered: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Head Attempts settled during the event. Joined input may settle with each head. */\n settled: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Submissions still nonterminal after the pass (suspended/unknown lanes stay honest). */\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** `rearmed` for dirty/autonomous work, `cleared` for stable waits or settlement. */\n alarm: Schema.Literals([\"rearmed\", \"cleared\"]),\n}) {}\n\n/** Fault boundaries around every maintenance-owned durable mutation. */\nexport type ThreadMaintenanceFailpointLocation =\n | \"maintenance:dirty:before\"\n | \"maintenance:dirty:after\"\n | \"maintenance:mutation:armed\"\n | \"maintenance:mutation:finished\"\n | \"maintenance:ensure:before\"\n | \"maintenance:ensure:after\"\n | \"maintenance:begin:before\"\n | \"maintenance:begin:after\"\n | \"maintenance:select:before\"\n | \"maintenance:select:after\"\n | \"maintenance:binding-retry:before\"\n | \"maintenance:binding-retry:after\"\n | \"maintenance:recovery-status:before\"\n | \"maintenance:recovery-status:after\"\n | \"maintenance:retry:before\"\n | \"maintenance:retry:after\"\n | \"maintenance:checkpoint:before\"\n | \"maintenance:checkpoint:after\"\n | \"maintenance:finish:before\"\n | \"maintenance:finish:after\";\n\nexport type ThreadMaintenanceFailpointHandler = (\n location: ThreadMaintenanceFailpointLocation,\n) => Effect.Effect<void>;\n\n/** Test-only fault authority; production uses the inert layer. */\nexport class ThreadMaintenanceFailpoint extends Context.Service<\n ThreadMaintenanceFailpoint,\n {\n readonly hit: ThreadMaintenanceFailpointHandler;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenanceFailpoint\") {\n static readonly layer = Layer.succeed(this)({ hit: () => Effect.void });\n}\n\n/**\n * Durable host publication of canonical records and ledger approval/abort/resolution intents.\n * The host owns schema-versioned cursors, destination idempotency and acknowledgement. Delivery\n * is at least once. Hooks must not write the alarm slot or mutate the supplied raw source ports.\n *\n * `invalidate`, `prepareGeneration` and `pendingDeadline` must be bounded local operations.\n * `prepareGeneration` durably invalidates a scan only when its generation changes; repeated\n * calls must preserve partial scan progress. It runs with no source mutation in flight.\n * Use this gate only for publication required before dependent native execution. Independent\n * UI relays and outboxes belong to ThreadHostMaintenance.\n * `drain` performs bounded delivery and persists retries before returning. A pending deadline\n * defers runtime recovery/Attempts, allowing committed host publications to drain first.\n * Unexpected hook failures leave the prearmed generation for retry. Hooks acquire per-call\n * resources with Effect.scoped; Layer construction owns incarnation resources (eviction need\n * not run finalizers). Do not hold a local hook behind network I/O or call back into producers.\n */\nexport interface ThreadPublicationService {\n readonly invalidate: Effect.Effect<void, DurableAlarmError>;\n readonly prepareGeneration: (generation: bigint) => Effect.Effect<void, DurableAlarmError>;\n readonly drain: Effect.Effect<void, DurableAlarmError>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}\n\n/** Opt in with `ThreadObject.layer(registrations, { publication: Layer.effect(ThreadPublication)(...) })`. */\nexport class ThreadPublication extends Context.Service<\n ThreadPublication,\n ThreadPublicationService\n>()(\"@effect-agent/platform-cloudflare/ThreadPublication\") {\n static readonly layer = Layer.succeed(this)({\n invalidate: Effect.void,\n prepareGeneration: () => Effect.void,\n drain: Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n });\n}\n\n/**\n * Host-assembled native message recovery. Preparation is a bounded local selection; the\n * driver bounds each actual Claim and persists its timeout/retry before `run` returns.\n * The alarm must not add a timer starting at selection: Claim setup and retry commits belong\n * to the driver. The prepared allowance decides only whether a wave fits this event.\n */\nexport const ThreadMessageDelivery = Context.Reference<{\n readonly prepare: Effect.Effect<\n {\n readonly timeoutMillis: number;\n readonly run: Effect.Effect<void, DurableAlarmError>;\n },\n DurableAlarmError\n >;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}>(\"@effect-agent/platform-cloudflare/ThreadMessageDelivery\", {\n defaultValue: () => ({\n prepare: Effect.succeed({ timeoutMillis: 1, run: Effect.void }),\n pendingDeadline: Effect.succeed(Option.none()),\n }),\n});\n\n/**\n * One independently schedulable application obligation. `run` selects and joins one finite\n * wave, including its retry/receipt commits. The alarm gives every lane an initial opportunity,\n * then checks its local pending deadline on completion, native progress, wakes and bounded scans.\n * No subscriptions, readiness acknowledgements, deadline sleeps or dispatch loops are needed.\n *\n * Declare a whole-wave allowance (1..300000ms), including selection, local commits and cleanup. A wave\n * starts only if that allowance fits the event and later arrivals cannot renew it. A failed\n * lane is not retried within the event. The alarm joins admitted work and closes its Scope\n * before reading durable deadlines under the shared ThreadMutationGate.\n *\n * `pendingDeadline` is bounded local control state, never a retained-history scan. Persist\n * envelopes/claims before dispatch; cancellation is local, not remote rollback. Network waits\n * and finalizers must be interruptible; short atomic commits may be uninterruptible. Mutations\n * use the shared gate and producers notify the existing WakeScheduler after commit. Hooks never\n * write the raw alarm slot. Required native publication gates belong to ThreadPublication.\n */\nexport interface ThreadHostMaintenanceLane {\n readonly dispatchTimeoutMillis: number;\n readonly run: Effect.Effect<void, DurableAlarmError, Scope.Scope>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}\n\n/** Independent lanes share the existing alarm; compose hosts by concatenating their lanes. */\nexport const ThreadHostMaintenance = Context.Reference<{\n readonly lanes: ReadonlyArray<ThreadHostMaintenanceLane>;\n}>(\"@effect-agent/platform-cloudflare/ThreadHostMaintenance\", {\n defaultValue: () => ({ lanes: [] }),\n});\n\nconst earliestDeadline = (\n left: Option.Option<number>,\n right: Option.Option<number>,\n): Option.Option<number> =>\n Option.isSome(left)\n ? Option.isSome(right)\n ? Option.some(Math.min(left.value, right.value))\n : left\n : right;\n\n/** @internal A committed source operation must not become a failed operation because delivery failed. */\nexport const publishCommitted = Effect.gen(function* () {\n const publication = yield* ThreadPublication;\n\n yield* publication.invalidate.pipe(Effect.andThen(publication.drain));\n}).pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterrupts(cause)\n ? Effect.interrupt\n : Effect.logError(\"Thread publication deferred after source commit\", cause),\n ),\n);\n\nconst MaintenanceGeneration = Schema.BigIntFromString.check(\n Schema.isGreaterThanOrEqualToBigInt(0n),\n);\n\nclass BindingRetry extends Schema.Class<BindingRetry>(\"BindingRetry\")({\n threadId: ThreadId,\n submissionId: SubmissionId,\n attempts: Schema.Natural,\n notBefore: Schema.Finite,\n reportedAt: Schema.Finite,\n}) {}\n\n/**\n * A durable observation of blocked recovery, independent of the execution journal. This is\n * neither a Settlement nor proof that external effects did not happen. A successful recovery\n * sweep clears it; repair must preserve canonical history and the original admission identity.\n */\nexport class ThreadRecoveryFault extends Schema.Class<ThreadRecoveryFault>(\n \"@effect-agent/platform-cloudflare/ThreadRecoveryFault\",\n)({\n schemaVersion: Schema.Literal(1),\n threadId: ThreadId,\n firstFailedAt: Schema.Finite,\n lastFailedAt: Schema.Finite,\n /** Earliest automatic recovery retry; new admissions do not erase this deadline. */\n retryAt: Schema.Finite,\n /** Saturates at 2^31 - 1; one observation per Thread per recovery sweep. */\n attempts: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(2_147_483_647)),\n failure: RecoveryFailure,\n}) {}\n\nconst recoveryFaultKey = (threadId: ThreadId) =>\n `effect-agent:thread-recovery-fault:v1:${threadId}`;\n\nconst decodeRecoveryFaultValue = Schema.decodeUnknownSync(ThreadRecoveryFault);\n\nconst decodeRecoveryFault = (threadId: ThreadId, encoded: unknown) => {\n const fault = decodeRecoveryFaultValue(encoded);\n\n if (fault.threadId !== threadId) throw new Error(\"Recovery status does not match its Thread key\");\n\n return fault;\n};\n\nconst encodeRecoveryFault = Schema.encodeSync(ThreadRecoveryFault);\n\ninterface NativePassResult {\n readonly phase: \"caught-up\" | \"actionable\";\n readonly nonterminal: number;\n readonly nextAttemptAt: number | undefined;\n readonly dispatched?: boolean;\n}\n\n/** Independent Threads share two bounded native slots; one active head per Thread. */\ninterface NativeDispatch {\n readonly scope: Scope.Scope;\n readonly active: Map<ThreadId, Fiber.Fiber<number, MaintenancePassFailure>>;\n readonly deferred: Set<ThreadId>;\n dispatched: number;\n settled: number;\n progressed: boolean;\n needsCheckpoint: boolean;\n generation?: bigint;\n scanGeneration?: bigint;\n}\n\nconst nativeDispatchConcurrency = 2;\n\n/** Event-local observations only; durable ingress keeps racing mutations dirty. */\ninterface NativeRecovery {\n readonly queue: Deferred.Deferred<ReadonlyArray<ThreadId>>;\n readonly pending: Set<ThreadId>;\n readonly loaded: Set<ThreadId>;\n readonly reports: Map<SubmissionId, RecoveryReport>;\n readonly faults: Map<ThreadId, ThreadRecoveryFault>;\n observation?: {\n readonly generation: bigint;\n readonly activeAtStart: number;\n };\n started: boolean;\n needsCheckpoint: boolean;\n recovered: number;\n repaired: boolean;\n}\n\ninterface MaintenanceObservation {\n generation?: bigint;\n nativeOnly: boolean;\n}\n\nclass MaintenanceRetry extends Schema.Class<MaintenanceRetry>(\"MaintenanceRetry\")({\n generation: MaintenanceGeneration,\n notBefore: Schema.Finite,\n nativeOnly: Schema.Boolean,\n stalls: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(30)),\n}) {}\n\n/** Versioned, platform-private maintenance state stored through Durable Object KV. */\nclass ThreadMaintenanceState extends Schema.Class<ThreadMaintenanceState>(\n \"@effect-agent/platform-cloudflare/ThreadMaintenanceState\",\n)({\n schemaVersion: Schema.Literal(1),\n dirty: MaintenanceGeneration,\n processed: MaintenanceGeneration,\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** One physical-owner cursor; old single-lane records need no conversion. */\n lastServedThreadId: Schema.optionalKey(ThreadId),\n /** Rotate old recovery independently of dispatch, including after eviction or timeout. */\n lastRecoveredThreadId: Schema.optionalKey(ThreadId),\n bindingRetries: Schema.optionalKey(Schema.Array(BindingRetry)),\n /** Absent on older records. A newer mutation makes this retry obsolete. */\n retry: Schema.optionalKey(MaintenanceRetry),\n}) {}\n\nconst MAINTENANCE_STATE_KEY = \"effect-agent:thread-maintenance:v1\";\nconst decodeMaintenanceState = Schema.decodeUnknownSync(ThreadMaintenanceState);\nconst encodeMaintenanceState = Schema.encodeSync(ThreadMaintenanceState);\n\nconst initialMaintenanceState = (): ThreadMaintenanceState =>\n ThreadMaintenanceState.make({\n schemaVersion: 1,\n // Bootstrap Objects created by the pre-generation release without scanning the ledger in\n // the constructor. One useful pass classifies and acknowledges any existing obligation.\n dirty: 1n,\n processed: 0n,\n nonterminal: 0,\n });\n\nconst readMaintenanceState = async (\n transaction: DurableObjectTransaction,\n): Promise<{ readonly state: ThreadMaintenanceState; readonly initialized: boolean }> => {\n const encoded = await transaction.get(MAINTENANCE_STATE_KEY);\n\n return encoded === undefined\n ? { state: initialMaintenanceState(), initialized: false }\n : { state: decodeMaintenanceState(encoded), initialized: true };\n};\n\nconst ensureTransactionAlarmBy = async (\n transaction: DurableObjectTransaction,\n deadline: number,\n): Promise<void> => {\n const scheduled = await transaction.getAlarm();\n\n if (scheduled === null || scheduled > deadline) {\n await transaction.setAlarm(deadline);\n }\n};\n\nconst stableExternalWait = (\n snapshot: SubmissionWorkItem,\n reports: ReadonlyMap<string, RecoveryReport>,\n): boolean => {\n const report = reports.get(snapshot.submissionId);\n const decision = report?.decision._tag;\n\n // An accepted abort still owes cleanup/settlement even if its claim was deferred this pass.\n if (decision === \"SettleAborted\") return false;\n switch (snapshot.state) {\n case \"suspended\":\n case \"joined\":\n return true;\n case \"unknown\":\n return report?.disposition === \"unknown\";\n case \"admitted\":\n return reports.get(snapshot.submissionId)?.decision._tag === \"AwaitParentEstablishment\";\n case \"input-applied\":\n case \"joining\":\n case \"ready\":\n case \"running\":\n case \"settled\":\n case \"terminalizing\":\n return false;\n }\n};\n\n/**\n * Shared prearm/acknowledgement boundary for ingress and runtime-owned producers.\n * `ThreadObject.layer` provides this same instance in its Services. Rebuilt runtime/maintenance\n * Layers must reuse that instance; a second gate cannot observe the native producers' activity.\n */\nexport class ThreadMutationGate extends Context.Service<\n ThreadMutationGate,\n {\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n /**\n * Native admission, approval, abort and unknown resolution keep the default true.\n * Projection/relay/reply receipt-only bookkeeping must use false: its local durable\n * pendingDeadline owns scheduling without creating native recovery debt.\n */\n options?: { readonly invalidatesRecovery: boolean },\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n readonly withSnapshot: <A, E, R>(\n body: (active: number) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/internal/ThreadMutationGate\") {\n static readonly layer = Layer.effect(this)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* CloudflareDurableRuntimeConfig;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n // A fresh incarnation has no live mutations; durable generations survive eviction.\n const activeMutations = yield* Ref.make(0);\n const generationGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const beginMutation = Effect.fn(\"ThreadMaintenance.beginMutation\")(function* (\n invalidatesRecovery: boolean,\n ) {\n yield* failpoint.hit(\"maintenance:dirty:before\");\n const now = yield* Clock.currentTimeMillis;\n\n yield* runTransaction(\"advance maintenance generation\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n const next = ThreadMaintenanceState.make({\n ...state,\n dirty: state.dirty + (invalidatesRecovery ? 1n : 0n),\n });\n\n if (invalidatesRecovery || !initialized)\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n // The earliest configured retry bounds a newly actionable mutation without relying\n // on its best-effort immediate wake hint.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n }),\n );\n yield* failpoint.hit(\"maintenance:dirty:after\");\n yield* Ref.update(activeMutations, (active) => active + 1);\n });\n\n const endMutation = generationGate.withPermit(\n Ref.update(activeMutations, (active) => Math.max(0, active - 1)),\n );\n\n const withMutation = <A, E, R>(\n body: Effect.Effect<A, E, R>,\n options?: { readonly invalidatesRecovery: boolean },\n ): Effect.Effect<A, E | DurableAlarmError, R> =>\n Effect.acquireUseRelease(\n generationGate.withPermit(beginMutation(options?.invalidatesRecovery ?? true)),\n () =>\n failpoint.hit(\"maintenance:mutation:armed\").pipe(\n Effect.andThen(body),\n Effect.tap(() => failpoint.hit(\"maintenance:mutation:finished\")),\n ),\n () => endMutation,\n );\n\n return ThreadMutationGate.of({\n withMutation,\n withSnapshot: (body) =>\n generationGate.withPermit(Effect.flatMap(Ref.get(activeMutations), body)),\n });\n }),\n );\n}\n\nexport type MaintenancePassFailure =\n | DurableWorkerFailure\n | DurableBindingFailure\n | DurableAlarmError\n | ThreadProjectionError;\n\n/**\n * Incremental, quiescent maintenance over a durable dirty/processed generation (issue #93).\n *\n * One physical event owns native scheduling, auxiliary delivery and final alarm rearming.\n *\n * 1. Prearm before any work. A caught-up native step uses the O(1) generation record without\n * recovery, ledger scans or canonical-history reads.\n * 2. Reconcile before each head Attempt, then checkpoint only the observed generation. A racing\n * producer keeps its generation dirty and immediately eligible. Quiescent native retries\n * retain their durable backoff.\n * 3. Admit at most two independent Thread Attempts, one active head per Thread.\n * Keep native and delivery admission open together while finite waves remain active, so\n * fresh replies and abort controls can progress during unrelated cleanup. Close atomically\n * at quiescence, or at the original ten-minute yield deadline, then join admitted waves.\n * 4. Native message delivery retains its driver-owned Claim deadline. Host/backfill waves are\n * bounded independently; incoming native work never restarts or cancels their attempts.\n * Auxiliary failures are reported after the current native opportunity.\n * 5. Close every event resource before the final gated deadline snapshot and alarm decision.\n * The whole event retains one fourteen-minute cooperative timeout.\n */\nexport class ThreadMaintenance extends Context.Service<\n ThreadMaintenance,\n {\n /** One idempotent pass; failures propagate after durably scheduling bounded recovery. */\n readonly pass: Effect.Effect<MaintenancePassReport, MaintenancePassFailure>;\n /**\n * Constructor gate: initialize/inspect only the O(1) maintenance record and ensure a dirty\n * generation has an alarm. It never scans the ledger or canonical history.\n */\n readonly ensureAlarm: Effect.Effect<void, MaintenancePassFailure>;\n /**\n * Authorize `explain`, then read one bounded local record without reading execution history.\n * None means no recorded fault, not proof of health or settlement. The host authenticates\n * callers and verifies local Thread membership before exposing this service across RPC.\n * Created, updated and cleared faults notify WakeScheduler after their durable commit.\n * Provide OperationAuthorizer when constructing this Layer, as for DurableAgentRuntime.\n */\n readonly recoveryStatus: (\n threadId: ThreadId,\n ) => Effect.Effect<Option.Option<ThreadRecoveryFault>, DurableAlarmError | OperationDenied>;\n /**\n * Serialize the pre-arm boundary with pass acknowledgement, advance the durable dirty\n * generation and arm the alarm in one transaction BEFORE running the caller's mutation.\n * A pass cannot acknowledge while that mutation remains in flight.\n */\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenance\") {\n static readonly layer: Layer.Layer<\n ThreadMaintenance,\n never,\n | ThreadMutationGate\n | ThreadPublication\n | ThreadProjectionMaintenance\n | DurableAgentRuntime\n | DurableRuntimeConfig\n | SubmissionLedger\n | WakeScheduler\n | DurableAlarmService\n | ThreadMaintenanceFailpoint\n | CloudflareDurableRuntimeConfig\n | DurableObjectContext\n | SqlClient\n > = Layer.effect(ThreadMaintenance)(\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const recoveryConfig = yield* DurableRuntimeConfig;\n const ledger = yield* SubmissionLedger;\n const wakes = yield* WakeScheduler;\n const alarm = yield* DurableAlarmService;\n const config = yield* CloudflareDurableRuntimeConfig;\n const { ctx } = yield* DurableObjectContext;\n const storage = DurableObjectStorage.fromDurableObjectStorage(ctx.storage);\n const runStorage = yield* makeStorageEffect;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n\n const mutations = yield* ThreadMutationGate;\n const publication = yield* ThreadPublication;\n const projection = yield* ThreadProjectionMaintenance;\n const messages = yield* ThreadMessageDelivery;\n const host = yield* ThreadHostMaintenance;\n const authorizer = yield* OperationAuthorizer;\n\n // A broken disposable index still needs a retry alarm and must not prevent startup.\n const projectionDeadline = projection.pendingDeadline.pipe(\n Effect.catchCauseIf(\n (cause) => !Cause.hasInterrupts(cause),\n (cause) =>\n Effect.logError(\"Thread projection deadline unavailable\", cause).pipe(\n Effect.as(Option.some(0)),\n ),\n ),\n );\n\n const pendingDeadline = Effect.gen(function* () {\n return earliestDeadline(\n earliestDeadline(yield* publication.pendingDeadline, yield* messages.pendingDeadline),\n earliestDeadline(\n yield* projectionDeadline,\n (yield* Effect.forEach(host.lanes, (lane) => lane.pendingDeadline)).reduce(\n earliestDeadline,\n Option.none<number>(),\n ),\n ),\n );\n });\n\n const maintenancePassGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const recoveryStatus = Effect.fn(\"ThreadMaintenance.recoveryStatus\")(function* (\n threadId: ThreadId,\n ) {\n yield* authorizer.authorize(\n OperationAuthorizationRequest.make({ operation: \"explain\", threadId }),\n );\n\n return yield* runTransaction(\"read Thread recovery status\", async () => {\n const encoded = await ctx.storage.get(recoveryFaultKey(threadId));\n\n return encoded === undefined\n ? Option.none()\n : Option.some(decodeRecoveryFault(threadId, encoded));\n });\n });\n\n const recordRecoveryStatus = Effect.fn(\"ThreadMaintenance.recordRecoveryStatus\")(function* (\n result: RecoverySweepResult,\n ) {\n const threads = new Map<ThreadId, RecoveryFailure | undefined>();\n\n for (const report of result.reports) threads.set(report.threadId, undefined);\n for (const blocked of result.blocked) threads.set(blocked.threadId, blocked.failure);\n if (threads.size === 0) return new Map<ThreadId, ThreadRecoveryFault>();\n const now = yield* Clock.currentTimeMillis;\n\n yield* failpoint.hit(\"maintenance:recovery-status:before\");\n\n const retained = yield* runTransaction(\"record Thread recovery status\", () =>\n ctx.storage.transaction(async (transaction) => {\n const changed: Array<ThreadId> = [];\n const newlyBlocked: Array<ThreadRecoveryFault> = [];\n const faults = new Map<ThreadId, ThreadRecoveryFault>();\n\n for (const [threadId, failure] of threads) {\n const key = recoveryFaultKey(threadId);\n const encoded = await transaction.get(key);\n\n const previous =\n encoded === undefined ? undefined : decodeRecoveryFault(threadId, encoded);\n\n if (failure === undefined) {\n if (previous !== undefined) {\n await transaction.delete(key);\n changed.push(threadId);\n }\n continue;\n }\n\n const fault = ThreadRecoveryFault.make({\n schemaVersion: 1,\n threadId,\n firstFailedAt: previous?.firstFailedAt ?? now,\n lastFailedAt: now,\n attempts: Math.min(2_147_483_647, (previous?.attempts ?? 0) + 1),\n retryAt: now + Math.min(60_000, 5_000 * 2 ** Math.min(30, previous?.attempts ?? 0)),\n failure,\n });\n\n await transaction.put(key, encodeRecoveryFault(fault));\n changed.push(threadId);\n faults.set(threadId, fault);\n if (previous === undefined) newlyBlocked.push(fault);\n }\n\n return { changed, newlyBlocked, faults };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:recovery-status:after\");\n // A healthy unchanged head must not wake its own maintenance loop.\n for (const threadId of retained.changed) yield* wakes.notify(threadId);\n for (const fault of retained.newlyBlocked)\n yield* Effect.logError(\n \"Native Thread recovery blocked; accepted work remains pending\",\n fault.failure.reason === \"defect\"\n ? Cause.die(fault.failure)\n : Cause.fail(fault.failure),\n ).pipe(Effect.annotateLogs({ threadId: fault.threadId }));\n\n return retained.faults;\n });\n\n const recoverThread = Effect.fn(\"ThreadMaintenance.recoverThread\")(function* (\n threadId: ThreadId,\n recovery: NativeRecovery,\n ) {\n const result = yield* runtime.runRecovery({ threadId });\n // Visibility is committed before a claim or any fallible auxiliary join.\n const faults = yield* recordRecoveryStatus(result);\n\n for (const report of result.reports) recovery.reports.set(report.submissionId, report);\n recovery.faults.delete(threadId);\n for (const [id, fault] of faults) recovery.faults.set(id, fault);\n recovery.recovered += result.reports.length + result.blocked.length;\n recovery.repaired ||= result.reports.some((report) => report.disposition === \"repaired\");\n });\n\n const ensureAlarm = Effect.fn(\"ThreadMaintenance.ensureAlarm\")(function* () {\n yield* failpoint.hit(\"maintenance:ensure:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const retry = yield* runTransaction(\"ensure maintenance alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n if (state.dirty > state.processed) {\n await ensureTransactionAlarmBy(\n transaction,\n state.retry?.generation === state.dirty\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : now + config.wakeScanInterval,\n );\n }\n\n return state.retry?.generation === state.dirty ? state.retry : undefined;\n }),\n );\n\n const deadline = yield* pendingDeadline;\n\n if (Option.isSome(deadline)) {\n yield* runTransaction(\"ensure publication alarm\", () =>\n ctx.storage.transaction((transaction) =>\n ensureTransactionAlarmBy(\n transaction,\n Math.max(\n now + minimumAlarmDelay,\n deadline.value <= now && retry !== undefined && !retry.nativeOnly\n ? Math.max(deadline.value, retry.notBefore)\n : deadline.value,\n ),\n ),\n ),\n );\n }\n yield* failpoint.hit(\"maintenance:ensure:after\");\n });\n\n const beginPass = Effect.fn(\"ThreadMaintenance.beginPass\")(function* (observed: {\n generation?: bigint;\n }) {\n yield* failpoint.hit(\"maintenance:begin:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const result = yield* runTransaction(\"begin maintenance pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n observed.generation = state.dirty;\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n const retryAt = state.retry?.generation === state.dirty ? state.retry.notBefore : 0;\n\n // Prearm before recovery or any host hook, including publication-only passes.\n // A completed pass may move this crash fallback later to its bounded retry.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n if (state.processed >= state.dirty || retryAt > now) {\n return {\n _tag: \"CaughtUp\" as const,\n nonterminal: state.nonterminal,\n };\n }\n\n return {\n _tag: \"Actionable\" as const,\n generation: state.dirty,\n nonterminal: state.nonterminal,\n stalls: state.retry?.generation === state.dirty ? state.retry.stalls : 0,\n };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:begin:after\");\n\n return result;\n });\n\n const backoffDelay = (priorStalls: number, jitter: number) => {\n const backoff = Math.min(\n config.alarmBackoffCap,\n config.alarmBackoffBase * 2 ** Math.min(priorStalls, 30),\n );\n\n // Jitter over [backoff/2, backoff] spreads retries without exceeding the cap.\n return Math.ceil(backoff / 2 + (backoff / 2) * jitter);\n };\n\n const rearmDelay = Effect.fn(\"ThreadMaintenance.rearmDelay\")(function* (\n progressed: boolean,\n priorStalls: number,\n ) {\n return progressed ? config.alarmBackoffBase : backoffDelay(priorStalls, yield* Random.next);\n });\n\n const rearmFailure = Effect.fn(\"ThreadMaintenance.rearmFailure\")(function* (\n observed: MaintenanceObservation,\n ) {\n const { generation, nativeOnly } = observed;\n\n if (generation === undefined) return;\n yield* failpoint.hit(\"maintenance:retry:before\");\n yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n // A failed deadline read must not prevent committing the native retry.\n const deadline = yield* pendingDeadline.pipe(\n Effect.catchCause(() => Effect.succeed(Option.none<number>())),\n );\n\n const now = yield* Clock.currentTimeMillis;\n\n const jitter = yield* Random.next;\n\n yield* runTransaction(\"back off failed maintenance\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const previous =\n state.retry?.generation === generation && state.retry.nativeOnly === nativeOnly\n ? state.retry\n : undefined;\n\n const retry = MaintenanceRetry.make({\n generation,\n notBefore: Math.max(\n previous?.notBefore ?? 0,\n now + backoffDelay(previous?.stalls ?? 0, jitter),\n ),\n nativeOnly,\n stalls: Math.min(30, (previous?.stalls ?? 0) + 1),\n });\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(ThreadMaintenanceState.make({ ...state, retry })),\n );\n\n // Never postpone a producer that raced the failed observation. Host work\n // retains its own deadline; an early delivery skips native recovery below.\n const nativeDeadline =\n active > 0 || state.dirty !== generation\n ? now + minimumAlarmDelay\n : retry.notBefore;\n\n await transaction.setAlarm(\n Math.max(\n now + minimumAlarmDelay,\n Option.isSome(deadline) && (nativeOnly || deadline.value > now)\n ? Math.min(nativeDeadline, deadline.value)\n : nativeDeadline,\n ),\n );\n }),\n );\n }),\n );\n yield* failpoint.hit(\"maintenance:retry:after\");\n });\n\n const beginNative = Effect.fn(\"ThreadMaintenance.beginNative\")(function* (\n observed: MaintenanceObservation,\n ) {\n return yield* mutations.withSnapshot((activeAtStart) =>\n Effect.gen(function* () {\n const generation = yield* beginPass(observed);\n\n if (generation._tag === \"Actionable\" && activeAtStart === 0) {\n // The gate excludes a producer starting between the snapshot and certification.\n yield* publication.prepareGeneration(generation.generation);\n }\n\n return { ...generation, activeAtStart };\n }),\n );\n });\n\n const attemptSelected = Effect.fn(\"ThreadMaintenance.attemptSelected\")(function* (\n selected: SubmissionWorkItem,\n previousRetries: ReadonlyArray<BindingRetry>,\n yieldAfter: DateTime.Utc,\n recovery: NativeRecovery,\n ): Effect.fn.Return<number, MaintenancePassFailure> {\n yield* recoverThread(selected.threadId, recovery);\n\n let bindingFailure: DurableBindingFailure | undefined;\n\n // A missing binding releases its slot after retaining this exact Submission\n // and committing its retry deadline below.\n const settlement = recovery.faults.has(selected.threadId)\n ? Option.none()\n : yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(\n Effect.catchTag(\"BindingUnavailable\", (failure) => {\n bindingFailure = failure;\n\n return Effect.succeed(Option.none());\n }),\n );\n\n const previous = previousRetries.find(\n (retry) => retry.submissionId === selected.submissionId,\n );\n\n let retry: BindingRetry | undefined;\n let reportBindingFailure = false;\n\n if (bindingFailure !== undefined) {\n const now = yield* Clock.currentTimeMillis;\n const attempts = Math.min(30, (previous?.attempts ?? 0) + 1);\n\n reportBindingFailure = previous === undefined || now - previous.reportedAt >= 15 * 60_000;\n retry = BindingRetry.make({\n threadId: selected.threadId,\n submissionId: selected.submissionId,\n attempts,\n notBefore: now + Math.min(60_000, 5_000 * 2 ** (attempts - 1)),\n reportedAt: reportBindingFailure ? now : (previous?.reportedAt ?? now),\n });\n }\n if (retry !== undefined || previous !== undefined) {\n // The Attempt released its Claim. Commit its binding wait (or clear) once,\n // before joining fallible auxiliary work. This local fact neither acknowledges\n // a generation nor changes the shared alarm.\n yield* failpoint.hit(\"maintenance:binding-retry:before\");\n yield* runStorage(\n \"record submission binding retry\",\n storage\n .transaction((transaction) =>\n Effect.gen(function* () {\n const encoded = yield* transaction.get(MAINTENANCE_STATE_KEY);\n\n const state =\n encoded === undefined\n ? initialMaintenanceState()\n : yield* Schema.decodeUnknownEffect(ThreadMaintenanceState)(encoded);\n\n const bindingRetries = [\n ...(state.bindingRetries ?? []).filter(\n (entry) => entry.submissionId !== selected.submissionId,\n ),\n ...(retry === undefined ? [] : [retry]),\n ];\n\n yield* transaction.put(\n MAINTENANCE_STATE_KEY,\n yield* Schema.encodeEffect(ThreadMaintenanceState)(\n ThreadMaintenanceState.make({ ...state, bindingRetries }),\n ),\n );\n }),\n )\n .pipe(Effect.mapError(alarmFailure(\"record submission binding retry\"))),\n );\n yield* failpoint.hit(\"maintenance:binding-retry:after\");\n }\n if (bindingFailure !== undefined) {\n yield* reportBindingFailure\n ? Effect.logError(\n \"Thread awaits a current agent binding; original work remains pending\",\n Cause.fail(bindingFailure),\n )\n : Effect.logDebug(\"Thread binding retry remains pending\", Cause.fail(bindingFailure));\n }\n\n return Option.isSome(settlement) ? 1 : 0;\n });\n\n const advance = Effect.fn(\"ThreadMaintenance.advance\")(function* (\n started: Effect.Success<ReturnType<typeof beginNative>>,\n yieldAfter: DateTime.Utc,\n observed: MaintenanceObservation,\n recovery: NativeRecovery,\n native: NativeDispatch,\n dispatch = true,\n reserved: ReadonlySet<ThreadId> = new Set(native.active.keys()),\n ): Effect.fn.Return<NativePassResult, MaintenancePassFailure> {\n const deadline = yield* publication.pendingDeadline;\n\n if (\n started._tag === \"Actionable\" ||\n (Option.isSome(deadline) && deadline.value <= (yield* Clock.currentTimeMillis))\n ) {\n yield* publication.drain;\n }\n const pending = yield* publication.pendingDeadline;\n\n if (started._tag === \"CaughtUp\" || Option.isSome(pending)) {\n const nextAttemptAt = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n\n const { state } = yield* runTransaction(\"read native maintenance deadline\", () =>\n ctx.storage.transaction((transaction) => readMaintenanceState(transaction)),\n );\n\n const native =\n active > 0 || state.dirty > state.processed\n ? state.retry?.generation === state.dirty && active === 0\n ? state.retry.notBefore\n : now + minimumAlarmDelay\n : Infinity;\n\n const next = Option.isSome(pending) ? pending.value : native;\n\n return Number.isFinite(next) ? Math.max(now + minimumAlarmDelay, next) : undefined;\n }),\n );\n\n return {\n phase: \"caught-up\",\n nonterminal: started.nonterminal,\n nextAttemptAt,\n };\n }\n if (native.generation !== started.generation) {\n native.deferred.clear();\n native.generation = started.generation;\n }\n // A stable generation with no freed slot needs no second ledger/history scan.\n // Enrollment precedes admission: never cache a scan overlapping a producer body,\n // which may make a head ready later without another generation increment.\n if (native.active.size > 0 && native.scanGeneration === started.generation) {\n return {\n phase: \"actionable\",\n nonterminal: started.nonterminal,\n nextAttemptAt: undefined,\n };\n }\n native.scanGeneration = started.activeAtStart === 0 ? started.generation : undefined;\n\n // Select from control state before reading execution history. A recovering or faulted\n // Thread cannot enter dispatch; old cleanup has its own scoped opportunity below.\n observed.nativeOnly = true;\n\n // Every checkpoint keeps the producer overlap that belongs to this recovery wave.\n const observation = (recovery.observation ??= {\n generation: started.generation,\n activeAtStart: started.activeAtStart,\n });\n\n const current = yield* Stream.runCollect(ledger.scanNonterminal);\n const selectionTime = yield* Clock.currentTimeMillis;\n\n yield* runTransaction(\"read Thread recovery deadlines\", async () => {\n for (const threadId of new Set(current.map((row) => row.threadId))) {\n if (recovery.loaded.has(threadId)) continue;\n const encoded = await ctx.storage.get(recoveryFaultKey(threadId));\n\n if (encoded !== undefined)\n recovery.faults.set(threadId, decodeRecoveryFault(threadId, encoded));\n recovery.loaded.add(threadId);\n }\n });\n const reports = recovery.reports;\n const recoveryFaults = recovery.faults;\n\n const waiting = (row: SubmissionWorkItem) =>\n !recovery.pending.has(row.threadId) &&\n !recoveryFaults.has(row.threadId) &&\n stableExternalWait(row, reports);\n\n const heads = new Map<ThreadId, SubmissionWorkItem>();\n\n for (const row of current) {\n // Only recovered uncertainty may release later input; accepted aborts retain FIFO.\n if (row.state === \"unknown\" && waiting(row)) continue;\n if (!heads.has(row.threadId)) heads.set(row.threadId, row);\n }\n const stopping = new Set<ThreadId>();\n\n for (const head of heads.values()) {\n if (\n head.state !== \"ready\" ||\n native.active.has(head.threadId) ||\n recovery.pending.has(head.threadId) ||\n recoveryFaults.has(head.threadId)\n )\n continue;\n\n // An accepted abort is cleanup even when its input was never claimed. This\n // control-only read must not decode the execution journal or a recovery snapshot.\n const intent = yield* isolateRecovery(\n ledger.readAbortIntent(AbortIntentRequest.make({ submissionId: head.submissionId })),\n {\n timeout: recoveryConfig.recoveryTimeout,\n phase: () => \"recovery\",\n operation: \"read abort intent\",\n },\n );\n\n if (Result.isSuccess(intent)) {\n if (intent.success !== undefined) stopping.add(head.threadId);\n } else {\n const faults = yield* recordRecoveryStatus(\n RecoverySweepResult.make({\n reports: [],\n blocked: [\n RecoveryBlocked.make({ threadId: head.threadId, failure: intent.failure }),\n ],\n }),\n );\n\n for (const [threadId, fault] of faults) recoveryFaults.set(threadId, fault);\n recovery.recovered++;\n }\n }\n\n const eligible = [...heads.values()]\n .filter(\n (head) =>\n !recovery.pending.has(head.threadId) &&\n !stopping.has(head.threadId) &&\n !recoveryFaults.has(head.threadId) &&\n !waiting(head) &&\n (head.state === \"ready\" || reports.has(head.submissionId)),\n )\n .map((head) => head.threadId)\n .sort();\n\n yield* failpoint.hit(\"maintenance:select:before\");\n\n const selection = yield* runTransaction(\"select maintenance lane\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const retries = (state.bindingRetries ?? []).filter(\n (retry) => heads.get(retry.threadId)?.submissionId === retry.submissionId,\n );\n\n const runnable = eligible.filter(\n (threadId) =>\n !reserved.has(threadId) &&\n !native.active.has(threadId) &&\n !native.deferred.has(threadId) &&\n !retries.some(\n (retry) => retry.threadId === threadId && retry.notBefore > selectionTime,\n ),\n );\n\n const pivot = Math.max(\n 0,\n runnable.findIndex(\n (threadId) =>\n state.lastServedThreadId === undefined || threadId > state.lastServedThreadId,\n ),\n );\n\n const selected = dispatch\n ? [...runnable.slice(pivot), ...runnable.slice(0, pivot)].slice(\n 0,\n nativeDispatchConcurrency - reserved.size,\n )\n : [];\n\n const next = selected.at(-1);\n\n if (next !== undefined) {\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(\n ThreadMaintenanceState.make({ ...state, lastServedThreadId: next }),\n ),\n );\n }\n\n const backlog = recovery.started\n ? []\n : [...heads.keys()].filter((threadId) => {\n const fault = recoveryFaults.get(threadId);\n\n return (\n !eligible.includes(threadId) &&\n (fault === undefined || fault.retryAt <= selectionTime)\n );\n });\n\n // One finite wave, one Thread at a time, with the runtime's per-Thread deadline.\n // This cursor ensures an event deadline/eviction cannot always restart at the front.\n const after = backlog.filter(\n (threadId) =>\n state.lastRecoveredThreadId === undefined || threadId > state.lastRecoveredThreadId,\n );\n\n const before = backlog.filter(\n (threadId) =>\n state.lastRecoveredThreadId !== undefined &&\n threadId <= state.lastRecoveredThreadId,\n );\n\n return { selected, retries, backlog: [...after, ...before] };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:select:after\");\n if (!recovery.started) {\n recovery.started = true;\n recovery.needsCheckpoint = selection.backlog.length > 0;\n for (const threadId of selection.backlog) recovery.pending.add(threadId);\n yield* Deferred.succeed(recovery.queue, selection.backlog);\n }\n\n for (const threadId of selection.selected) {\n const selected = heads.get(threadId);\n\n if (selected === undefined) continue;\n // Reserve before recovery or claim acquisition. The durable Claim remains the\n // authority; this event-local reservation only prevents duplicate dispatch.\n native.dispatched++;\n native.active.set(\n threadId,\n yield* Effect.forkIn(\n attemptSelected(selected, selection.retries, yieldAfter, recovery),\n native.scope,\n ),\n );\n }\n\n if (native.active.size > 0) {\n // Active Attempts own their claims and may still append/settle. Only acknowledge\n // a generation after joining every admitted native Attempt.\n return {\n phase: \"actionable\",\n nonterminal: current.length,\n nextAttemptAt: undefined,\n dispatched: selection.selected.length > 0,\n };\n }\n const retries = selection.retries;\n\n const remaining = yield* Stream.runCollect(ledger.scanNonterminal);\n const waitingHeads = new Map<ThreadId, boolean>();\n\n const autonomous = remaining.some((snapshot) => {\n if (snapshot.state === \"unknown\" && waiting(snapshot)) return false;\n const headWaiting = waitingHeads.get(snapshot.threadId);\n\n if (headWaiting === undefined) waitingHeads.set(snapshot.threadId, waiting(snapshot));\n // FIFO followers cannot execute through a stable external wait. Only plain queued\n // input is dormant here; admission repairs and accepted aborts still need a pass.\n if (\n headWaiting === true &&\n snapshot.state === \"ready\" &&\n reports.get(snapshot.submissionId)?.decision._tag === \"ApplyInput\"\n )\n return false;\n\n return !waiting(snapshot);\n });\n\n const progressed = native.progressed || recovery.repaired;\n\n const now = yield* Clock.currentTimeMillis;\n const ordinaryDelay = autonomous ? yield* rearmDelay(progressed, started.stalls) : 0;\n\n const nextEligible = [...recoveryFaults.values()]\n .map((fault) => fault.retryAt)\n .concat(\n eligible.map(\n (threadId) =>\n retries.find((retry) => retry.submissionId === heads.get(threadId)?.submissionId)\n ?.notBefore ?? now,\n ),\n );\n\n const retryDelay =\n nextEligible.length === 0 ? 0 : Math.max(0, Math.min(...nextEligible) - now);\n\n const delay = Math.max(ordinaryDelay, retryDelay);\n\n // Checkpoint native progress without changing the physical alarm. Auxiliary\n // delivery remains live; later mutations still advance the shared generation.\n yield* failpoint.hit(\"maintenance:checkpoint:before\");\n\n const nextAttemptAt = yield* mutations.withSnapshot((active) =>\n runTransaction(\"checkpoint native maintenance\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const mutationOverlap =\n observation.activeAtStart > 0 || started.activeAtStart > 0 || active > 0;\n\n const processed =\n autonomous || mutationOverlap\n ? state.processed\n : state.processed > observation.generation\n ? state.processed\n : observation.generation;\n\n // Enrollment precedes the mutation body. A retry from an overlapping snapshot\n // must not defer work that becomes ready later in that same generation.\n const canBackoff = !mutationOverlap && state.dirty === started.generation;\n\n const next = ThreadMaintenanceState.make({\n ...Struct.omit(state, [\"retry\"]),\n processed,\n nonterminal: remaining.length,\n bindingRetries: (state.bindingRetries ?? []).filter((retry) =>\n remaining.some((row) => row.submissionId === retry.submissionId),\n ),\n ...(autonomous && !progressed && canBackoff\n ? {\n retry: MaintenanceRetry.make({\n generation: started.generation,\n notBefore: now + delay,\n nativeOnly: true,\n stalls: Math.min(30, started.stalls + 1),\n }),\n }\n : {}),\n });\n\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n if (autonomous) {\n return now + (canBackoff ? delay : minimumAlarmDelay);\n }\n\n return mutationOverlap || next.dirty > next.processed\n ? now + minimumAlarmDelay\n : undefined;\n }),\n ),\n );\n\n yield* failpoint.hit(\"maintenance:checkpoint:after\");\n native.deferred.clear();\n native.progressed = false;\n native.needsCheckpoint = false;\n\n return {\n phase: \"actionable\",\n nonterminal: remaining.length,\n nextAttemptAt,\n };\n });\n\n const pass = Effect.fn(\"ThreadMaintenance.pass\")(function* (\n yieldAfter: DateTime.Utc,\n dispatchUntil: DateTime.Utc,\n observed: MaintenanceObservation,\n ): Effect.fn.Return<MaintenancePassReport, MaintenancePassFailure, Scope.Scope> {\n // Subscribe before the first native snapshot. Hints accelerate rechecks; the\n // bounded scan and durable generation still recover dropped notifications.\n const notified = (yield* Stream.toPull(wakes.wakes)).pipe(\n Effect.asVoid,\n Effect.catch(() => Effect.never),\n );\n\n // A wake may observe temporary backoff while this event's recovery is still running.\n // Its completion must retain the original actionable observation for acknowledgement.\n const started = yield* beginNative(observed);\n\n // This scope owns every admitted finite wave, including native advancement.\n // Close it before final alarm rearming, including on failure or event interruption.\n const auxiliaryScope = yield* Effect.acquireRelease(Scope.make(\"parallel\"), (scope, exit) =>\n Scope.close(scope, exit),\n );\n\n const fork = <A, E>(work: Effect.Effect<A, E>) => Effect.forkIn(work, auxiliaryScope);\n\n // Each lane has at most one finite wave. A completion is retained until the single\n // scheduling loop observes it; a busy sibling cannot consume another lane's hint.\n const lanes = host.lanes.map((lane) => ({\n ...lane,\n initial: true,\n check: true,\n exhausted: false,\n fiber: undefined as Fiber.Fiber<boolean, DurableAlarmError> | undefined,\n }));\n\n let messageExhausted = false;\n let delivery: Fiber.Fiber<void, DurableAlarmError> | undefined;\n let failure: Cause.Cause<MaintenancePassFailure> | undefined;\n\n const recovery: NativeRecovery = {\n queue: yield* Deferred.make<ReadonlyArray<ThreadId>>(),\n pending: new Set(),\n loaded: new Set(),\n reports: new Map(),\n faults: new Map(),\n started: false,\n needsCheckpoint: false,\n recovered: 0,\n repaired: false,\n };\n\n const recoveryFiber = yield* fork(\n Effect.gen(function* () {\n for (const threadId of yield* Deferred.await(recovery.queue)) {\n yield* failpoint.hit(\"maintenance:select:before\");\n yield* runTransaction(\"select old recovery lane\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(\n ThreadMaintenanceState.make({ ...state, lastRecoveredThreadId: threadId }),\n ),\n );\n }),\n );\n yield* failpoint.hit(\"maintenance:select:after\");\n yield* recoverThread(threadId, recovery);\n recovery.pending.delete(threadId);\n yield* wakes.notify(threadId);\n }\n }),\n );\n\n // Backfill is one disposable wave; native and host work keep their own opportunities.\n const backfill = yield* fork(\n drainDue.pipe(\n Effect.provideService(ThreadProjectionMaintenance, projection),\n Effect.timeoutOption(config.projectionDispatchTimeoutMillis),\n ),\n );\n\n let backfillObserved = false;\n let recoveryObserved = false;\n\n const dispatch: NativeDispatch = {\n scope: auxiliaryScope,\n active: new Map(),\n deferred: new Set(),\n dispatched: 0,\n settled: 0,\n progressed: false,\n needsCheckpoint: false,\n };\n\n let native: Fiber.Fiber<NativePassResult, MaintenancePassFailure> | undefined = yield* fork(\n advance(started, yieldAfter, observed, recovery, dispatch),\n );\n\n let result: NativePassResult = {\n phase: \"caught-up\",\n nonterminal: started.nonterminal,\n nextAttemptAt: undefined,\n };\n\n let phase = result.phase;\n let nativeCheck = false;\n const until = DateTime.toEpochMillis(yieldAfter);\n const dispatchEnd = DateTime.toEpochMillis(dispatchUntil);\n\n const checkLanes = () => {\n for (const lane of lanes) lane.check = true;\n };\n\n while (true) {\n if (native?.pollUnsafe() !== undefined) {\n result = yield* Fiber.join(native);\n native = undefined;\n if (result.phase === \"actionable\") phase = \"actionable\";\n observed.nativeOnly = dispatch.active.size > 0;\n if (result.dispatched === true && dispatch.active.size < nativeDispatchConcurrency) {\n dispatch.scanGeneration = undefined;\n nativeCheck = true;\n }\n // An empty initial scan still opens exactly one old-recovery opportunity.\n recovery.started = true;\n yield* Deferred.succeed(recovery.queue, []);\n checkLanes();\n }\n for (const [threadId, attempt] of dispatch.active) {\n const exit = attempt.pollUnsafe();\n\n if (exit === undefined) continue;\n dispatch.active.delete(threadId);\n dispatch.scanGeneration = undefined;\n if (Exit.isFailure(exit)) return yield* Effect.failCause(exit.cause);\n dispatch.settled += exit.value;\n dispatch.progressed ||= exit.value > 0;\n dispatch.needsCheckpoint = true;\n if (exit.value === 0) dispatch.deferred.add(threadId);\n nativeCheck = true;\n checkLanes();\n }\n if (!recoveryObserved && recoveryFiber.pollUnsafe() !== undefined) {\n yield* Fiber.join(recoveryFiber);\n recoveryObserved = true;\n dispatch.scanGeneration = undefined;\n nativeCheck ||= recovery.needsCheckpoint;\n }\n if (!backfillObserved) {\n const exit = backfill.pollUnsafe();\n\n if (exit !== undefined) {\n backfillObserved = true;\n if (Exit.isFailure(exit)) failure ??= exit.cause;\n }\n }\n for (const lane of lanes) {\n const exit = lane.fiber?.pollUnsafe();\n\n if (exit === undefined) continue;\n lane.fiber = undefined;\n if (Exit.isFailure(exit)) {\n failure ??= exit.cause;\n lane.exhausted = true;\n } else {\n lane.check ||= exit.value;\n }\n }\n const deliveryExit = delivery?.pollUnsafe();\n\n if (deliveryExit !== undefined) {\n delivery = undefined;\n if (Exit.isFailure(deliveryExit)) {\n failure ??= deliveryExit.cause;\n messageExhausted = true;\n }\n }\n\n // A failed auxiliary lane is exhausted for this event. Its error must not\n // retire healthy admission, delivery or native work that still has an allowance.\n const now = yield* Clock.currentTimeMillis;\n\n if (now >= until) break;\n\n for (const lane of lanes) {\n if (lane.fiber !== undefined || lane.exhausted || !lane.check) continue;\n lane.check = false;\n lane.fiber = yield* fork(\n Effect.gen(function* () {\n yield* Schema.decodeEffect(AuxiliaryDispatchMillis)(\n lane.dispatchTimeoutMillis,\n ).pipe(\n Effect.mapError((cause) =>\n DurableAlarmError.make({\n operation: \"host dispatch allowance\",\n message:\n \"Declare an integer whole-wave allowance between 1 and 300000 milliseconds\",\n cause,\n }),\n ),\n );\n if ((yield* Clock.currentTimeMillis) + lane.dispatchTimeoutMillis > dispatchEnd) {\n lane.exhausted = true;\n\n return false;\n }\n\n return yield* Effect.gen(function* () {\n if (!lane.initial) {\n const deadline = yield* lane.pendingDeadline;\n\n if (\n Option.isNone(deadline) ||\n deadline.value > (yield* Clock.currentTimeMillis)\n )\n return false;\n }\n const selectedAt = yield* Clock.currentTimeMillis;\n\n if (\n selectedAt >= until ||\n selectedAt + lane.dispatchTimeoutMillis > dispatchEnd\n ) {\n lane.exhausted = true;\n\n return false;\n }\n lane.initial = false;\n yield* lane.run;\n\n return true;\n }).pipe(\n // Cleanup shares this wave's original allowance.\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: lane.dispatchTimeoutMillis,\n orElse: () =>\n DurableAlarmError.make({\n operation: \"host dispatch allowance\",\n message:\n \"The admitted host wave exceeded its allowance; durable work remains pending\",\n }),\n }),\n );\n }),\n );\n }\n if (delivery === undefined && !messageExhausted) {\n // Selection is bounded local work. Fork only an actual due wave, so an empty\n // deadline check cannot extend retirement or consume another scheduling turn.\n const selected = yield* Effect.gen(function* () {\n const deadline = yield* messages.pendingDeadline;\n\n return Option.isSome(deadline) && deadline.value <= (yield* Clock.currentTimeMillis)\n ? Option.some(yield* messages.prepare)\n : Option.none();\n }).pipe(Effect.exit);\n\n if (Exit.isFailure(selected)) {\n failure ??= selected.cause;\n messageExhausted = true;\n } else if (Option.isSome(selected.value)) {\n const wave = selected.value.value;\n const selectedAt = yield* Clock.currentTimeMillis;\n\n if (selectedAt >= until || selectedAt + wave.timeoutMillis > dispatchEnd) {\n messageExhausted = true;\n } else {\n // No second timeout: the driver owes the Claim's timeout/retry commit.\n delivery = yield* fork(wave.run);\n }\n }\n }\n\n // Retire a quiet event before consuming hints queued during its native Attempt.\n // Recovery still gets its checkpoint and, if needed, initial dispatch opportunity.\n if (\n native === undefined &&\n dispatch.active.size === 0 &&\n recoveryObserved &&\n !recovery.needsCheckpoint &&\n backfillObserved &&\n delivery === undefined &&\n lanes.every((lane) => lane.fiber === undefined)\n )\n break;\n\n if (\n native === undefined &&\n nativeCheck &&\n dispatch.active.size < nativeDispatchConcurrency\n ) {\n nativeCheck = false;\n const nativeCheckpoint = dispatch.needsCheckpoint && dispatch.active.size === 0;\n const checkpoint = (recoveryObserved && recovery.needsCheckpoint) || nativeCheckpoint;\n\n if (checkpoint) recovery.needsCheckpoint = false;\n // Keep this opportunity's reservations across beginNative's storage awaits.\n // A finishing Attempt cannot turn a refill into another same-Thread Attempt.\n const reserved = new Set(dispatch.active.keys());\n\n native = yield* fork(\n Effect.gen(function* () {\n const awakened = checkpoint ? started : yield* beginNative(observed);\n\n return yield* advance(\n awakened,\n yieldAfter,\n observed,\n recovery,\n dispatch,\n !nativeCheckpoint && (!checkpoint || dispatch.settled === 0),\n reserved,\n );\n }),\n );\n }\n\n const next = Math.min(\n native === undefined ? (result.nextAttemptAt ?? Infinity) : Infinity,\n now + config.wakeScanInterval,\n until,\n );\n\n const completing = [\n ...(native === undefined ? [] : [native]),\n ...dispatch.active.values(),\n ...(recoveryObserved ? [] : [recoveryFiber]),\n ...(backfillObserved ? [] : [backfill]),\n ...(delivery === undefined ? [] : [delivery]),\n ...lanes.flatMap((lane) => (lane.fiber === undefined ? [] : [lane.fiber])),\n ];\n\n const ready = yield* Effect.raceAllFirst([\n ...completing.map((fiber) =>\n Fiber.await<unknown, MaintenancePassFailure>(fiber).pipe(\n Effect.as(\"completed\" as const),\n ),\n ),\n Effect.raceFirst(notified, Effect.sleep(Math.max(0, next - now))).pipe(\n Effect.as(\"scan\" as const),\n ),\n ]);\n\n if (ready === \"scan\") {\n nativeCheck = true;\n checkLanes();\n }\n }\n // Dispatch is closed. Join each admitted wave without renewing its allowance.\n // Message Claims retain their driver's own timer and local retry commit.\n if (native !== undefined) {\n result = yield* Fiber.join(native);\n if (result.phase === \"actionable\") phase = \"actionable\";\n observed.nativeOnly = dispatch.active.size > 0;\n recovery.started = true;\n yield* Deferred.succeed(recovery.queue, []);\n }\n for (const attempt of dispatch.active.values()) {\n const settled = yield* Fiber.join(attempt);\n\n dispatch.settled += settled;\n dispatch.progressed ||= settled > 0;\n }\n dispatch.active.clear();\n observed.nativeOnly = false;\n for (const fiber of [\n recoveryFiber,\n backfill,\n ...(delivery === undefined ? [] : [delivery]),\n ...lanes.flatMap((lane) => (lane.fiber === undefined ? [] : [lane.fiber])),\n ]) {\n // Await exits without failing fast: every admitted wave owns its original\n // bounded allowance and cleanup even if another wave has already failed.\n const exit = yield* Fiber.await<unknown, MaintenancePassFailure>(fiber);\n\n if (Exit.isFailure(exit)) failure ??= exit.cause;\n }\n if (failure !== undefined) return yield* Effect.failCause(failure);\n if (recovery.needsCheckpoint || dispatch.dispatched > 0) {\n result = yield* advance(started, yieldAfter, observed, recovery, dispatch, false);\n if (result.phase === \"actionable\") phase = \"actionable\";\n }\n yield* Scope.close(auxiliaryScope, Exit.void);\n yield* failpoint.hit(\"maintenance:finish:before\");\n\n const disposition = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n const latest = yield* pendingDeadline;\n const now = yield* Clock.currentTimeMillis;\n\n return yield* runTransaction(\"finish maintenance event\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const native =\n active > 0 || state.dirty > state.processed\n ? state.retry?.generation === state.dirty && active === 0\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : state.dirty === observed.generation && active === 0\n ? (result.nextAttemptAt ?? now + config.wakeScanInterval)\n : now + minimumAlarmDelay\n : Infinity;\n\n const next = Option.isSome(latest) ? Math.min(native, latest.value) : native;\n\n if (Number.isFinite(next)) {\n await transaction.setAlarm(Math.max(now + minimumAlarmDelay, next));\n\n return \"rearmed\" as const;\n }\n await transaction.deleteAlarm();\n\n return \"cleared\" as const;\n }),\n );\n }),\n );\n\n yield* failpoint.hit(\"maintenance:finish:after\");\n\n const report = MaintenancePassReport.make({\n phase,\n recovered: recovery.recovered,\n settled: dispatch.settled,\n nonterminal: result.nonterminal,\n alarm: disposition,\n });\n\n yield* Effect.annotateCurrentSpan({\n phase: report.phase,\n recovered: report.recovered,\n settled: report.settled,\n nonterminal: report.nonterminal,\n alarm: report.alarm,\n });\n\n return report;\n });\n\n return ThreadMaintenance.of({\n // A mid-pass immediate hint is droppable; durable dirty state decides the final alarm.\n pass: Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const yieldAfter = DateTime.makeUnsafe(now + 10 * 60_000);\n const dispatchUntil = DateTime.makeUnsafe(now + 14 * 60_000);\n const observed: MaintenanceObservation = { nativeOnly: false };\n\n return yield* alarm.withWakesDeferred(\n maintenancePassGate.withPermit(\n Effect.scoped(pass(yieldAfter, dispatchUntil, observed)).pipe(\n // Close event-owned auxiliary work and release Attempt ownership before\n // failure rearming, while still holding the pass permit.\n Effect.onErrorIf(\n () => true,\n () => rearmFailure(observed),\n ),\n ),\n ),\n );\n }).pipe(\n // Include permit waiting, recovery and acknowledgement in the event deadline.\n // Interruption releases Attempt ownership, leaving the prearmed dirty generation\n // for recovery. It never changes the logical Run duration or settles a policy failure.\n // This cooperative timer cannot preempt synchronous CPU work or stuck finalizers.\n Effect.timeoutOrElse({\n duration: \"14 minutes\",\n orElse: () =>\n DurableAlarmError.make({\n operation: \"maintenance pass deadline\",\n message:\n \"The maintenance event exceeded its 14 minute deadline; durable recovery remains pending\",\n }),\n }),\n ),\n ensureAlarm: mutations.withSnapshot(() => ensureAlarm()),\n recoveryStatus,\n withMutation: (body) =>\n mutations.withMutation(\n body.pipe(\n Effect.tap(() =>\n publishCommitted.pipe(Effect.provideService(ThreadPublication, publication)),\n ),\n ),\n ),\n });\n }),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Alarm.mjs","names":[],"sources":["../src/Alarm.ts"],"sourcesContent":["import {\n Cause,\n Clock,\n Context,\n DateTime,\n Deferred,\n Effect,\n Exit,\n Fiber,\n Layer,\n Option,\n Random,\n Ref,\n Result,\n Schema,\n Scope,\n Semaphore,\n Stream,\n Struct,\n} from \"effect\";\nimport { type DurableBindingFailure } from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n isolateRecovery,\n RecoveryBlocked,\n RecoveryFailure,\n type DurableWorkerFailure,\n type RecoveryReport,\n RecoverySweepResult,\n} from \"effect-agent/durable-agent-runtime\";\nimport { ThreadId, SubmissionId } from \"effect-agent/identifiers\";\nimport {\n OperationAuthorizationRequest,\n OperationAuthorizer,\n type OperationDenied,\n} from \"effect-agent/operation-authorizer\";\nimport {\n AbortIntentRequest,\n SubmissionLedger,\n type SubmissionWorkItem,\n} from \"effect-agent/submission-ledger\";\nimport {\n ThreadProjectionMaintenance,\n drainDue,\n type ThreadProjectionError,\n} from \"effect-agent/thread-projection-maintenance\";\nimport { WakeScheduler } from \"effect-agent/wake-scheduler\";\nimport { DurableObjectStorage } from \"effect-cf\";\nimport { SqlClient } from \"effect/unstable/sql/SqlClient\";\n\nimport { DurableObjectContext } from \"./CloudflareBindings.ts\";\nimport { AuxiliaryDispatchMillis, CloudflareDurableRuntimeConfig } from \"./CloudflareConfig.ts\";\nimport { safeCauseMessage } from \"./internal/boundary.ts\";\n\n/**\n * The single multiplexed Durable Object alarm (decision D-P6-2). A Durable Object has ONE\n * alarm slot; every cadence the Node host ran on fibers (wake scan, lease expiry, settlement\n * and abort re-checks, retry backoff) multiplexes into one idempotent maintenance pass, and\n * the slot always holds the EARLIEST deadline any caller asked for.\n *\n * The alarm invariant (plan §1.4): every committed actionable mutation carries a newer durable\n * maintenance generation and a committed alarm. Stable externally-driven waits may be\n * nonterminal without retaining an alarm; their resolving mutation advances the generation and\n * restores the alarm atomically.\n */\n\n/** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */\nexport class DurableAlarmError extends Schema.TaggedError<DurableAlarmError>()(\n \"DurableAlarmError\",\n {\n operation: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\nconst alarmFailure =\n (operation: string) =>\n (cause: unknown): DurableAlarmError =>\n DurableAlarmError.make({\n operation,\n message: safeCauseMessage(cause, \"The Cloudflare alarm API failed without a diagnostic\"),\n cause,\n });\n\n// SQL and raw KV/alarm operations share one physical SQLite transaction. Reserve its\n// connection for each short storage operation, never around a mutation or snapshot body.\nconst makeStorageEffect = Effect.map(\n SqlClient,\n (sql) =>\n <A, R>(operation: string, execute: Effect.Effect<A, DurableAlarmError, R>) =>\n Effect.flatMap(Effect.serviceOption(sql.transactionService), (current) => {\n const body = Effect.uninterruptible(execute);\n\n return current._tag === \"Some\"\n ? body\n : Effect.scoped(\n Effect.andThen(sql.reserve.pipe(Effect.mapError(alarmFailure(operation))), body),\n );\n }),\n);\n\nconst makeStorageOperation = Effect.map(\n makeStorageEffect,\n (run) =>\n <A>(operation: string, execute: () => Promise<A>) =>\n run(operation, Effect.tryPromise({ try: execute, catch: alarmFailure(operation) })),\n);\n\n/** `ctx.storage` alarm slot as an Effect service; storage is truth, never a memory field. */\nexport class DurableAlarmService extends Context.Service<\n DurableAlarmService,\n {\n /** The scheduled deadline in epoch milliseconds, if any. */\n readonly scheduled: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n /** Replace the slot with this deadline. */\n readonly scheduleAt: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /** Keep the EARLIER of the existing deadline and this one (the multiplexing rule). */\n readonly ensureScheduledBy: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /**\n * Arm an immediate alarm (the durable, coalescing local wake) — DEFERRED while a\n * maintenance pass is executing. Workerd cancels an in-flight alarm handler when a new\n * EARLIER deadline is written during its execution (`requestScheduledAlarm`), and the\n * maintenance pass runs INSIDE the alarm handler: an immediate wake landing mid-pass\n * (a routed port mutation, a sibling's `wake()`, the coordinator's own local notify)\n * would kill the running Attempt — manufacturing an ownership loss no real eviction\n * caused, and routing open uncertain-class Tool Calls into spurious Unknown Outcomes.\n * Deferral is contract-safe: wakes are droppable hints, every mutating entry point\n * pre-arms BEFORE its first durable mutation (the alarm invariant never rests on this\n * call). The pass's durable generation check observes any racing mutation, so the\n * in-memory hint does not need to be flushed after a stable wait is acknowledged.\n */\n readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;\n /**\n * Run one maintenance pass with wake deferral (see `scheduleNow`). Calls made while `body`\n * executes are droppable promptness hints; correctness rests on the durable generation.\n */\n readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;\n /** Clear the slot; correctness-sensitive clears live in maintenance generation transactions. */\n readonly cancel: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableAlarmService\") {\n static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext | SqlClient> =\n Layer.effect(DurableAlarmService)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n /**\n * In-memory pass bookkeeping — a pure CACHE, never state: a fresh incarnation has no\n * running pass, and a deferred wake lost to eviction was only ever a promptness hint\n * on top of the already-committed pre-armed alarm.\n */\n const runningPasses = yield* Ref.make(0);\n\n const storageOperation = yield* makeStorageOperation;\n\n const scheduled = storageOperation(\"get alarm\", () => ctx.storage.getAlarm()).pipe(\n Effect.map((deadline) =>\n deadline === null ? Option.none<number>() : Option.some(deadline),\n ),\n );\n\n const scheduleAt = (epochMillis: number) =>\n storageOperation(\"set alarm\", () => ctx.storage.setAlarm(epochMillis));\n\n const ensureScheduledBy = (epochMillis: number) =>\n storageOperation(\"ensure alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const existing = await transaction.getAlarm();\n\n if (existing === null || existing > epochMillis) {\n await transaction.setAlarm(epochMillis);\n }\n }),\n );\n\n const armNow = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => ensureScheduledBy(now)),\n );\n\n const scheduleNow = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) => (passes > 0 ? Effect.void : armNow)),\n );\n\n const withWakesDeferred = <A, E, R>(body: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Ref.update(runningPasses, (passes) => passes + 1).pipe(\n Effect.andThen(body),\n Effect.ensuring(Ref.update(runningPasses, (passes) => passes - 1)),\n );\n\n const cancel = storageOperation(\"delete alarm\", () => ctx.storage.deleteAlarm());\n\n return DurableAlarmService.of({\n scheduled,\n scheduleAt,\n ensureScheduledBy,\n scheduleNow,\n withWakesDeferred,\n cancel,\n });\n }),\n );\n}\n\n/** What one maintenance pass did — auditable evidence mirroring `NodeDurableHost`'s report. */\nexport class MaintenancePassReport extends Schema.Class<MaintenancePassReport>(\n \"@effect-agent/platform-cloudflare/MaintenancePassReport\",\n)({\n /** `caught-up` ran no runtime work (publication may be pending); `actionable` ran recovery. */\n phase: Schema.Literals([\"caught-up\", \"actionable\"]),\n /** Recovery decisions and Thread faults observed during this event. */\n recovered: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Head Attempts settled during the event. Joined input may settle with each head. */\n settled: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Submissions still nonterminal after the pass (suspended/unknown lanes stay honest). */\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** `rearmed` for dirty/autonomous work, `cleared` for stable waits or settlement. */\n alarm: Schema.Literals([\"rearmed\", \"cleared\"]),\n}) {}\n\n/** Fault boundaries around every maintenance-owned durable mutation. */\nexport type ThreadMaintenanceFailpointLocation =\n | \"maintenance:dirty:before\"\n | \"maintenance:dirty:after\"\n | \"maintenance:mutation:armed\"\n | \"maintenance:mutation:finished\"\n | \"maintenance:ensure:before\"\n | \"maintenance:ensure:after\"\n | \"maintenance:begin:before\"\n | \"maintenance:begin:after\"\n | \"maintenance:select:before\"\n | \"maintenance:select:after\"\n | \"maintenance:binding-retry:before\"\n | \"maintenance:binding-retry:after\"\n | \"maintenance:recovery-status:before\"\n | \"maintenance:recovery-status:after\"\n | \"maintenance:retry:before\"\n | \"maintenance:retry:after\"\n | \"maintenance:checkpoint:before\"\n | \"maintenance:checkpoint:after\"\n | \"maintenance:finish:before\"\n | \"maintenance:finish:after\";\n\nexport type ThreadMaintenanceFailpointHandler = (\n location: ThreadMaintenanceFailpointLocation,\n) => Effect.Effect<void>;\n\n/** Test-only fault authority; production uses the inert layer. */\nexport class ThreadMaintenanceFailpoint extends Context.Service<\n ThreadMaintenanceFailpoint,\n {\n readonly hit: ThreadMaintenanceFailpointHandler;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenanceFailpoint\") {\n static readonly layer = Layer.succeed(this)({ hit: () => Effect.void });\n}\n\n/**\n * Durable host publication of canonical records and ledger approval/abort/resolution intents.\n * The host owns schema-versioned cursors, destination idempotency and acknowledgement. Delivery\n * is at least once. Hooks must not write the alarm slot or mutate the supplied raw source ports.\n *\n * `invalidate`, `prepareGeneration` and `pendingDeadline` must be bounded local operations.\n * `prepareGeneration` durably invalidates a scan only when its generation changes; repeated\n * calls must preserve partial scan progress. It runs with no source mutation in flight.\n * Use this gate only for publication required before dependent native execution. Independent\n * UI relays and outboxes belong to ThreadHostMaintenance.\n * `drain` performs bounded delivery and persists retries before returning. A pending deadline\n * defers runtime recovery/Attempts, allowing committed host publications to drain first.\n * Unexpected hook failures leave the prearmed generation for retry. Hooks acquire per-call\n * resources with Effect.scoped; Layer construction owns incarnation resources (eviction need\n * not run finalizers). Do not hold a local hook behind network I/O or call back into producers.\n */\nexport interface ThreadPublicationService {\n readonly invalidate: Effect.Effect<void, DurableAlarmError>;\n readonly prepareGeneration: (generation: bigint) => Effect.Effect<void, DurableAlarmError>;\n readonly drain: Effect.Effect<void, DurableAlarmError>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}\n\n/** Opt in with `ThreadObject.layer(registrations, { publication: Layer.effect(ThreadPublication)(...) })`. */\nexport class ThreadPublication extends Context.Service<\n ThreadPublication,\n ThreadPublicationService\n>()(\"@effect-agent/platform-cloudflare/ThreadPublication\") {\n static readonly layer = Layer.succeed(this)({\n invalidate: Effect.void,\n prepareGeneration: () => Effect.void,\n drain: Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n });\n}\n\n/**\n * Host-assembled native message recovery. Preparation is a bounded local selection; the\n * driver bounds each actual Claim and persists its timeout/retry before `run` returns.\n * The alarm must not add a timer starting at selection: Claim setup and retry commits belong\n * to the driver. The prepared allowance decides only whether a wave fits this event.\n */\nexport const ThreadMessageDelivery = Context.Reference<{\n readonly prepare: Effect.Effect<\n {\n readonly timeoutMillis: number;\n readonly run: Effect.Effect<void, DurableAlarmError>;\n },\n DurableAlarmError\n >;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}>(\"@effect-agent/platform-cloudflare/ThreadMessageDelivery\", {\n defaultValue: () => ({\n prepare: Effect.succeed({ timeoutMillis: 1, run: Effect.void }),\n pendingDeadline: Effect.succeed(Option.none()),\n }),\n});\n\n/**\n * One independently schedulable application obligation. `run` selects and joins one finite\n * wave, including its retry/receipt commits. The alarm gives every lane an initial opportunity,\n * then checks its local pending deadline on completion, native progress, wakes and bounded scans.\n * No subscriptions, readiness acknowledgements, deadline sleeps or dispatch loops are needed.\n *\n * Declare a whole-wave allowance (1..300000ms), including selection, local commits and cleanup. A wave\n * starts only if that allowance fits the event and later arrivals cannot renew it. A failed\n * lane is not retried within the event. The alarm joins admitted work and closes its Scope\n * before reading durable deadlines under the shared ThreadMutationGate.\n *\n * `pendingDeadline` is bounded local control state, never a retained-history scan. Persist\n * envelopes/claims before dispatch; cancellation is local, not remote rollback. Network waits\n * and finalizers must be interruptible; short atomic commits may be uninterruptible. Mutations\n * use the shared gate and producers notify the existing WakeScheduler after commit. Hooks never\n * write the raw alarm slot. Required native publication gates belong to ThreadPublication.\n */\nexport interface ThreadHostMaintenanceLane {\n readonly dispatchTimeoutMillis: number;\n readonly run: Effect.Effect<void, DurableAlarmError, Scope.Scope>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}\n\n/** Independent lanes share the existing alarm; compose hosts by concatenating their lanes. */\nexport const ThreadHostMaintenance = Context.Reference<{\n readonly lanes: ReadonlyArray<ThreadHostMaintenanceLane>;\n}>(\"@effect-agent/platform-cloudflare/ThreadHostMaintenance\", {\n defaultValue: () => ({ lanes: [] }),\n});\n\nconst earliestDeadline = (\n left: Option.Option<number>,\n right: Option.Option<number>,\n): Option.Option<number> =>\n Option.isSome(left)\n ? Option.isSome(right)\n ? Option.some(Math.min(left.value, right.value))\n : left\n : right;\n\n/** @internal A committed source operation must not become a failed operation because delivery failed. */\nexport const publishCommitted = Effect.gen(function* () {\n const publication = yield* ThreadPublication;\n\n yield* publication.invalidate.pipe(Effect.andThen(publication.drain));\n}).pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterrupts(cause)\n ? Effect.interrupt\n : Effect.logError(\"Thread publication deferred after source commit\", cause),\n ),\n);\n\nconst MaintenanceGeneration = Schema.BigIntFromString.check(\n Schema.isGreaterThanOrEqualToBigInt(0n),\n);\n\nclass BindingRetry extends Schema.Class<BindingRetry>(\"BindingRetry\")({\n threadId: ThreadId,\n submissionId: SubmissionId,\n attempts: Schema.Natural,\n notBefore: Schema.Finite,\n reportedAt: Schema.Finite,\n}) {}\n\n/**\n * A durable observation of blocked recovery, independent of the execution journal. This is\n * neither a Settlement nor proof that external effects did not happen. A successful recovery\n * sweep clears it; repair must preserve canonical history and the original admission identity.\n */\nexport class ThreadRecoveryFault extends Schema.Class<ThreadRecoveryFault>(\n \"@effect-agent/platform-cloudflare/ThreadRecoveryFault\",\n)({\n schemaVersion: Schema.Literal(1),\n threadId: ThreadId,\n firstFailedAt: Schema.Finite,\n lastFailedAt: Schema.Finite,\n /** Earliest automatic recovery retry; new admissions do not erase this deadline. */\n retryAt: Schema.Finite,\n /** Saturates at 2^31 - 1; one observation per Thread per recovery sweep. */\n attempts: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(2_147_483_647)),\n failure: RecoveryFailure,\n}) {}\n\nconst recoveryFaultKey = (threadId: ThreadId) =>\n `effect-agent:thread-recovery-fault:v1:${threadId}`;\n\nconst decodeRecoveryFaultValue = Schema.decodeUnknownSync(ThreadRecoveryFault);\n\nconst decodeRecoveryFault = (threadId: ThreadId, encoded: unknown) => {\n const fault = decodeRecoveryFaultValue(encoded);\n\n if (fault.threadId !== threadId) throw new Error(\"Recovery status does not match its Thread key\");\n\n return fault;\n};\n\nconst encodeRecoveryFault = Schema.encodeSync(ThreadRecoveryFault);\n\ninterface NativePassResult {\n readonly phase: \"caught-up\" | \"actionable\";\n readonly nonterminal: number;\n readonly nextAttemptAt: number | undefined;\n readonly dispatched?: boolean;\n}\n\n/** Independent Threads share two bounded native slots; one active head per Thread. */\ninterface NativeDispatch {\n readonly scope: Scope.Scope;\n readonly active: Map<ThreadId, Fiber.Fiber<number, MaintenancePassFailure>>;\n readonly deferred: Set<ThreadId>;\n dispatched: number;\n settled: number;\n progressed: boolean;\n needsCheckpoint: boolean;\n generation?: bigint;\n scanGeneration?: bigint;\n}\n\nconst nativeDispatchConcurrency = 2;\n\n/** Event-local observations only; durable ingress keeps racing mutations dirty. */\ninterface NativeRecovery {\n readonly queue: Deferred.Deferred<ReadonlyArray<ThreadId>>;\n readonly pending: Set<ThreadId>;\n readonly loaded: Set<ThreadId>;\n readonly reports: Map<SubmissionId, RecoveryReport>;\n readonly faults: Map<ThreadId, ThreadRecoveryFault>;\n observation?: {\n readonly generation: bigint;\n readonly activeAtStart: number;\n };\n started: boolean;\n needsCheckpoint: boolean;\n recovered: number;\n repaired: boolean;\n}\n\ninterface MaintenanceObservation {\n generation?: bigint;\n nativeOnly: boolean;\n}\n\nclass MaintenanceRetry extends Schema.Class<MaintenanceRetry>(\"MaintenanceRetry\")({\n generation: MaintenanceGeneration,\n notBefore: Schema.Finite,\n nativeOnly: Schema.Boolean,\n stalls: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(30)),\n}) {}\n\n/** Versioned, platform-private maintenance state stored through Durable Object KV. */\nclass ThreadMaintenanceState extends Schema.Class<ThreadMaintenanceState>(\n \"@effect-agent/platform-cloudflare/ThreadMaintenanceState\",\n)({\n schemaVersion: Schema.Literal(1),\n dirty: MaintenanceGeneration,\n processed: MaintenanceGeneration,\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** One physical-owner cursor; old single-lane records need no conversion. */\n lastServedThreadId: Schema.optionalKey(ThreadId),\n /** Rotate old recovery independently of dispatch, including after eviction or timeout. */\n lastRecoveredThreadId: Schema.optionalKey(ThreadId),\n bindingRetries: Schema.optionalKey(Schema.Array(BindingRetry)),\n /** Absent on older records. A newer mutation makes this retry obsolete. */\n retry: Schema.optionalKey(MaintenanceRetry),\n}) {}\n\nconst MAINTENANCE_STATE_KEY = \"effect-agent:thread-maintenance:v1\";\nconst decodeMaintenanceState = Schema.decodeUnknownSync(ThreadMaintenanceState);\nconst encodeMaintenanceState = Schema.encodeSync(ThreadMaintenanceState);\n\nconst initialMaintenanceState = (): ThreadMaintenanceState =>\n ThreadMaintenanceState.make({\n schemaVersion: 1,\n // Bootstrap Objects created by the pre-generation release without scanning the ledger in\n // the constructor. One useful pass classifies and acknowledges any existing obligation.\n dirty: 1n,\n processed: 0n,\n nonterminal: 0,\n });\n\nconst readMaintenanceState = async (\n transaction: DurableObjectTransaction,\n): Promise<{ readonly state: ThreadMaintenanceState; readonly initialized: boolean }> => {\n const encoded = await transaction.get(MAINTENANCE_STATE_KEY);\n\n return encoded === undefined\n ? { state: initialMaintenanceState(), initialized: false }\n : { state: decodeMaintenanceState(encoded), initialized: true };\n};\n\nconst ensureTransactionAlarmBy = async (\n transaction: DurableObjectTransaction,\n deadline: number,\n): Promise<void> => {\n const scheduled = await transaction.getAlarm();\n\n if (scheduled === null || scheduled > deadline) {\n await transaction.setAlarm(deadline);\n }\n};\n\nconst stableExternalWait = (\n snapshot: SubmissionWorkItem,\n reports: ReadonlyMap<string, RecoveryReport>,\n): boolean => {\n const report = reports.get(snapshot.submissionId);\n const decision = report?.decision._tag;\n\n // An accepted abort still owes cleanup/settlement even if its claim was deferred this pass.\n if (decision === \"SettleAborted\") return false;\n switch (snapshot.state) {\n case \"suspended\":\n case \"joined\":\n return true;\n case \"unknown\":\n return report?.disposition === \"unknown\";\n case \"admitted\":\n return reports.get(snapshot.submissionId)?.decision._tag === \"AwaitParentEstablishment\";\n case \"input-applied\":\n case \"joining\":\n case \"ready\":\n case \"running\":\n case \"settled\":\n case \"terminalizing\":\n return false;\n }\n};\n\n/**\n * Shared prearm/acknowledgement boundary for ingress and runtime-owned producers.\n * `ThreadObject.layer` provides this same instance in its Services. Rebuilt runtime/maintenance\n * Layers must reuse that instance; a second gate cannot observe the native producers' activity.\n */\nexport class ThreadMutationGate extends Context.Service<\n ThreadMutationGate,\n {\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n /**\n * Native admission, approval, abort and unknown resolution keep the default true.\n * Projection/relay/reply receipt-only bookkeeping must use false: its local durable\n * pendingDeadline owns scheduling without creating native recovery debt.\n */\n options?: { readonly invalidatesRecovery: boolean },\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n readonly withSnapshot: <A, E, R>(\n body: (active: number) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/internal/ThreadMutationGate\") {\n static readonly layer = Layer.effect(this)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* CloudflareDurableRuntimeConfig;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n // A fresh incarnation has no live mutations; durable generations survive eviction.\n const activeMutations = yield* Ref.make(0);\n const generationGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const beginMutation = Effect.fn(\"ThreadMaintenance.beginMutation\")(function* (\n invalidatesRecovery: boolean,\n ) {\n yield* failpoint.hit(\"maintenance:dirty:before\");\n const now = yield* Clock.currentTimeMillis;\n\n yield* runTransaction(\"advance maintenance generation\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n const next = ThreadMaintenanceState.make({\n ...state,\n dirty: state.dirty + (invalidatesRecovery ? 1n : 0n),\n });\n\n if (invalidatesRecovery || !initialized)\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n // The earliest configured retry bounds a newly actionable mutation without relying\n // on its best-effort immediate wake hint.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n }),\n );\n yield* failpoint.hit(\"maintenance:dirty:after\");\n yield* Ref.update(activeMutations, (active) => active + 1);\n });\n\n const endMutation = generationGate.withPermit(\n Ref.update(activeMutations, (active) => Math.max(0, active - 1)),\n );\n\n const withMutation = <A, E, R>(\n body: Effect.Effect<A, E, R>,\n options?: { readonly invalidatesRecovery: boolean },\n ): Effect.Effect<A, E | DurableAlarmError, R> =>\n Effect.acquireUseRelease(\n generationGate.withPermit(beginMutation(options?.invalidatesRecovery ?? true)),\n () =>\n failpoint.hit(\"maintenance:mutation:armed\").pipe(\n Effect.andThen(body),\n Effect.tap(() => failpoint.hit(\"maintenance:mutation:finished\")),\n ),\n () => endMutation,\n );\n\n return ThreadMutationGate.of({\n withMutation,\n withSnapshot: (body) =>\n generationGate.withPermit(Effect.flatMap(Ref.get(activeMutations), body)),\n });\n }),\n );\n}\n\nexport type MaintenancePassFailure =\n | DurableWorkerFailure\n | DurableBindingFailure\n | DurableAlarmError\n | ThreadProjectionError;\n\n/**\n * Incremental, quiescent maintenance over a durable dirty/processed generation (issue #93).\n *\n * One physical event owns native scheduling, auxiliary delivery and final alarm rearming.\n *\n * 1. Prearm before any work. A caught-up native step uses the O(1) generation record without\n * recovery, ledger scans or canonical-history reads.\n * 2. Reconcile before each head Attempt, then checkpoint only the observed generation. A racing\n * producer keeps its generation dirty and immediately eligible. Quiescent native retries\n * retain their durable backoff.\n * 3. Admit at most two independent Thread Attempts, one active head per Thread.\n * Keep native and delivery admission open together while finite waves remain active, so\n * fresh replies and abort controls can progress during unrelated cleanup. Close atomically\n * at quiescence, or at the original ten-minute yield deadline, then join admitted waves.\n * 4. Native message delivery retains its driver-owned Claim deadline. Host/backfill waves are\n * bounded independently; incoming native work never restarts or cancels their attempts.\n * Auxiliary failures are reported after the current native opportunity.\n * 5. Close every event resource before the final gated deadline snapshot and alarm decision.\n * The whole event retains one fourteen-minute cooperative timeout.\n */\nexport class ThreadMaintenance extends Context.Service<\n ThreadMaintenance,\n {\n /** One idempotent pass; failures propagate after durably scheduling bounded recovery. */\n readonly pass: Effect.Effect<MaintenancePassReport, MaintenancePassFailure>;\n /**\n * Constructor gate: initialize/inspect only the O(1) maintenance record and ensure a dirty\n * generation has an alarm. It never scans the ledger or canonical history.\n */\n readonly ensureAlarm: Effect.Effect<void, MaintenancePassFailure>;\n /**\n * Authorize `explain`, then read one bounded local record without reading execution history.\n * None means no recorded fault, not proof of health or settlement. The host authenticates\n * callers and verifies local Thread membership before exposing this service across RPC.\n * Created, updated and cleared faults notify WakeScheduler after their durable commit.\n * Provide OperationAuthorizer when constructing this Layer, as for DurableAgentRuntime.\n */\n readonly recoveryStatus: (\n threadId: ThreadId,\n ) => Effect.Effect<Option.Option<ThreadRecoveryFault>, DurableAlarmError | OperationDenied>;\n /**\n * Serialize the pre-arm boundary with pass acknowledgement, advance the durable dirty\n * generation and arm the alarm in one transaction BEFORE running the caller's mutation.\n * A pass cannot acknowledge while that mutation remains in flight.\n */\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenance\") {\n static readonly layer: Layer.Layer<\n ThreadMaintenance,\n never,\n | ThreadMutationGate\n | ThreadPublication\n | ThreadProjectionMaintenance\n | DurableAgentRuntime\n | DurableRuntimeConfig\n | SubmissionLedger\n | WakeScheduler\n | DurableAlarmService\n | ThreadMaintenanceFailpoint\n | CloudflareDurableRuntimeConfig\n | DurableObjectContext\n | SqlClient\n > = Layer.effect(ThreadMaintenance)(\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const recoveryConfig = yield* DurableRuntimeConfig;\n const ledger = yield* SubmissionLedger;\n const wakes = yield* WakeScheduler;\n const alarm = yield* DurableAlarmService;\n const config = yield* CloudflareDurableRuntimeConfig;\n const { ctx } = yield* DurableObjectContext;\n const storage = DurableObjectStorage.fromDurableObjectStorage(ctx.storage);\n const runStorage = yield* makeStorageEffect;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n\n const mutations = yield* ThreadMutationGate;\n const publication = yield* ThreadPublication;\n const projection = yield* ThreadProjectionMaintenance;\n const messages = yield* ThreadMessageDelivery;\n const host = yield* ThreadHostMaintenance;\n const authorizer = yield* OperationAuthorizer;\n\n // A broken disposable index still needs a retry alarm and must not prevent startup.\n const projectionDeadline = projection.pendingDeadline.pipe(\n Effect.catchCauseIf(\n (cause) => !Cause.hasInterrupts(cause),\n (cause) =>\n Effect.logError(\"Thread projection deadline unavailable\", cause).pipe(\n Effect.as(Option.some(0)),\n ),\n ),\n );\n\n const pendingDeadline = Effect.gen(function* () {\n return earliestDeadline(\n earliestDeadline(yield* publication.pendingDeadline, yield* messages.pendingDeadline),\n earliestDeadline(\n yield* projectionDeadline,\n (yield* Effect.forEach(host.lanes, (lane) => lane.pendingDeadline)).reduce(\n earliestDeadline,\n Option.none<number>(),\n ),\n ),\n );\n });\n\n const maintenancePassGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const recoveryStatus = Effect.fn(\"ThreadMaintenance.recoveryStatus\")(function* (\n threadId: ThreadId,\n ) {\n yield* authorizer.authorize(\n OperationAuthorizationRequest.make({ operation: \"explain\", threadId }),\n );\n\n return yield* runTransaction(\"read Thread recovery status\", async () => {\n const encoded = await ctx.storage.get(recoveryFaultKey(threadId));\n\n return encoded === undefined\n ? Option.none()\n : Option.some(decodeRecoveryFault(threadId, encoded));\n });\n });\n\n const recordRecoveryStatus = Effect.fn(\"ThreadMaintenance.recordRecoveryStatus\")(function* (\n result: RecoverySweepResult,\n ) {\n const threads = new Map<ThreadId, RecoveryFailure | undefined>();\n\n for (const report of result.reports) threads.set(report.threadId, undefined);\n for (const blocked of result.blocked) threads.set(blocked.threadId, blocked.failure);\n if (threads.size === 0) return new Map<ThreadId, ThreadRecoveryFault>();\n const now = yield* Clock.currentTimeMillis;\n\n yield* failpoint.hit(\"maintenance:recovery-status:before\");\n\n const retained = yield* runTransaction(\"record Thread recovery status\", () =>\n ctx.storage.transaction(async (transaction) => {\n const changed: Array<ThreadId> = [];\n const newlyBlocked: Array<ThreadRecoveryFault> = [];\n const faults = new Map<ThreadId, ThreadRecoveryFault>();\n\n for (const [threadId, failure] of threads) {\n const key = recoveryFaultKey(threadId);\n const encoded = await transaction.get(key);\n\n const previous =\n encoded === undefined ? undefined : decodeRecoveryFault(threadId, encoded);\n\n if (failure === undefined) {\n if (previous !== undefined) {\n await transaction.delete(key);\n changed.push(threadId);\n }\n continue;\n }\n\n const fault = ThreadRecoveryFault.make({\n schemaVersion: 1,\n threadId,\n firstFailedAt: previous?.firstFailedAt ?? now,\n lastFailedAt: now,\n attempts: Math.min(2_147_483_647, (previous?.attempts ?? 0) + 1),\n retryAt: now + Math.min(60_000, 5_000 * 2 ** Math.min(30, previous?.attempts ?? 0)),\n failure,\n });\n\n await transaction.put(key, encodeRecoveryFault(fault));\n changed.push(threadId);\n faults.set(threadId, fault);\n if (previous === undefined) newlyBlocked.push(fault);\n }\n\n return { changed, newlyBlocked, faults };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:recovery-status:after\");\n // A healthy unchanged head must not wake its own maintenance loop.\n for (const threadId of retained.changed) yield* wakes.notify(threadId);\n for (const fault of retained.newlyBlocked)\n yield* Effect.logError(\n \"Native Thread recovery blocked; accepted work remains pending\",\n fault.failure.reason === \"defect\"\n ? Cause.die(fault.failure)\n : Cause.fail(fault.failure),\n ).pipe(Effect.annotateLogs({ threadId: fault.threadId }));\n\n return retained.faults;\n });\n\n const recoverThread = Effect.fn(\"ThreadMaintenance.recoverThread\")(function* (\n threadId: ThreadId,\n recovery: NativeRecovery,\n ) {\n const result = yield* runtime.runRecovery({ threadId });\n // Visibility is committed before a claim or any fallible auxiliary join.\n const faults = yield* recordRecoveryStatus(result);\n\n for (const report of result.reports) recovery.reports.set(report.submissionId, report);\n recovery.faults.delete(threadId);\n for (const [id, fault] of faults) recovery.faults.set(id, fault);\n recovery.recovered += result.reports.length + result.blocked.length;\n recovery.repaired ||= result.reports.some((report) => report.disposition === \"repaired\");\n });\n\n const ensureAlarm = Effect.fn(\"ThreadMaintenance.ensureAlarm\")(function* () {\n yield* failpoint.hit(\"maintenance:ensure:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const retry = yield* runTransaction(\"ensure maintenance alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n if (state.dirty > state.processed) {\n await ensureTransactionAlarmBy(\n transaction,\n state.retry?.generation === state.dirty\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : now + config.wakeScanInterval,\n );\n }\n\n return state.retry?.generation === state.dirty ? state.retry : undefined;\n }),\n );\n\n const deadline = yield* pendingDeadline;\n\n if (Option.isSome(deadline)) {\n yield* runTransaction(\"ensure publication alarm\", () =>\n ctx.storage.transaction((transaction) =>\n ensureTransactionAlarmBy(\n transaction,\n Math.max(\n now + minimumAlarmDelay,\n deadline.value <= now && retry !== undefined && !retry.nativeOnly\n ? Math.max(deadline.value, retry.notBefore)\n : deadline.value,\n ),\n ),\n ),\n );\n }\n yield* failpoint.hit(\"maintenance:ensure:after\");\n });\n\n const beginPass = Effect.fn(\"ThreadMaintenance.beginPass\")(function* (observed: {\n generation?: bigint;\n }) {\n yield* failpoint.hit(\"maintenance:begin:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const result = yield* runTransaction(\"begin maintenance pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n observed.generation = state.dirty;\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n const retryAt = state.retry?.generation === state.dirty ? state.retry.notBefore : 0;\n\n // Prearm before recovery or any host hook, including publication-only passes.\n // A completed pass may move this crash fallback later to its bounded retry.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n if (state.processed >= state.dirty || retryAt > now) {\n return {\n _tag: \"CaughtUp\" as const,\n nonterminal: state.nonterminal,\n };\n }\n\n return {\n _tag: \"Actionable\" as const,\n generation: state.dirty,\n nonterminal: state.nonterminal,\n stalls: state.retry?.generation === state.dirty ? state.retry.stalls : 0,\n };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:begin:after\");\n\n return result;\n });\n\n const backoffDelay = (priorStalls: number, jitter: number) => {\n const backoff = Math.min(\n config.alarmBackoffCap,\n config.alarmBackoffBase * 2 ** Math.min(priorStalls, 30),\n );\n\n // Jitter over [backoff/2, backoff] spreads retries without exceeding the cap.\n return Math.ceil(backoff / 2 + (backoff / 2) * jitter);\n };\n\n const rearmDelay = Effect.fn(\"ThreadMaintenance.rearmDelay\")(function* (\n progressed: boolean,\n priorStalls: number,\n ) {\n return progressed ? config.alarmBackoffBase : backoffDelay(priorStalls, yield* Random.next);\n });\n\n const rearmFailure = Effect.fn(\"ThreadMaintenance.rearmFailure\")(function* (\n observed: MaintenanceObservation,\n ) {\n const { generation, nativeOnly } = observed;\n\n if (generation === undefined) return;\n yield* failpoint.hit(\"maintenance:retry:before\");\n yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n // A failed deadline read must not prevent committing the native retry.\n const deadline = yield* pendingDeadline.pipe(\n Effect.catchCause(() => Effect.succeed(Option.none<number>())),\n );\n\n const now = yield* Clock.currentTimeMillis;\n\n const jitter = yield* Random.next;\n\n yield* runTransaction(\"back off failed maintenance\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const previous =\n state.retry?.generation === generation && state.retry.nativeOnly === nativeOnly\n ? state.retry\n : undefined;\n\n const retry = MaintenanceRetry.make({\n generation,\n notBefore: Math.max(\n previous?.notBefore ?? 0,\n now + backoffDelay(previous?.stalls ?? 0, jitter),\n ),\n nativeOnly,\n stalls: Math.min(30, (previous?.stalls ?? 0) + 1),\n });\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(ThreadMaintenanceState.make({ ...state, retry })),\n );\n\n // Never postpone a producer that raced the failed observation. Host work\n // retains its own deadline; an early delivery skips native recovery below.\n const nativeDeadline =\n active > 0 || state.dirty !== generation\n ? now + minimumAlarmDelay\n : retry.notBefore;\n\n await transaction.setAlarm(\n Math.max(\n now + minimumAlarmDelay,\n Option.isSome(deadline) && (nativeOnly || deadline.value > now)\n ? Math.min(nativeDeadline, deadline.value)\n : nativeDeadline,\n ),\n );\n }),\n );\n }),\n );\n yield* failpoint.hit(\"maintenance:retry:after\");\n });\n\n const beginNative = Effect.fn(\"ThreadMaintenance.beginNative\")(function* (\n observed: MaintenanceObservation,\n ) {\n return yield* mutations.withSnapshot((activeAtStart) =>\n Effect.gen(function* () {\n const generation = yield* beginPass(observed);\n\n if (generation._tag === \"Actionable\" && activeAtStart === 0) {\n // The gate excludes a producer starting between the snapshot and certification.\n yield* publication.prepareGeneration(generation.generation);\n }\n\n return { ...generation, activeAtStart };\n }),\n );\n });\n\n const attemptSelected = Effect.fn(\"ThreadMaintenance.attemptSelected\")(function* (\n selected: SubmissionWorkItem,\n previousRetries: ReadonlyArray<BindingRetry>,\n yieldAfter: DateTime.Utc,\n recovery: NativeRecovery,\n ): Effect.fn.Return<number, MaintenancePassFailure> {\n yield* recoverThread(selected.threadId, recovery);\n\n let bindingFailure: DurableBindingFailure | undefined;\n\n // A missing binding releases its slot after retaining this exact Submission\n // and committing its retry deadline below.\n const settlement = recovery.faults.has(selected.threadId)\n ? Option.none()\n : yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(\n Effect.catchTag(\"BindingUnavailable\", (failure) => {\n bindingFailure = failure;\n\n return Effect.succeed(Option.none());\n }),\n );\n\n const previous = previousRetries.find(\n (retry) => retry.submissionId === selected.submissionId,\n );\n\n let retry: BindingRetry | undefined;\n let reportBindingFailure = false;\n\n if (bindingFailure !== undefined) {\n const now = yield* Clock.currentTimeMillis;\n const attempts = Math.min(30, (previous?.attempts ?? 0) + 1);\n\n reportBindingFailure = previous === undefined || now - previous.reportedAt >= 15 * 60_000;\n retry = BindingRetry.make({\n threadId: selected.threadId,\n submissionId: selected.submissionId,\n attempts,\n notBefore: now + Math.min(60_000, 5_000 * 2 ** (attempts - 1)),\n reportedAt: reportBindingFailure ? now : (previous?.reportedAt ?? now),\n });\n }\n if (retry !== undefined || previous !== undefined) {\n // The Attempt released its Claim. Commit its binding wait (or clear) once,\n // before joining fallible auxiliary work. This local fact neither acknowledges\n // a generation nor changes the shared alarm.\n yield* failpoint.hit(\"maintenance:binding-retry:before\");\n yield* runStorage(\n \"record submission binding retry\",\n storage\n .transaction((transaction) =>\n Effect.gen(function* () {\n const encoded = yield* transaction.get(MAINTENANCE_STATE_KEY);\n\n const state =\n encoded === undefined\n ? initialMaintenanceState()\n : yield* Schema.decodeUnknownEffect(ThreadMaintenanceState)(encoded);\n\n const bindingRetries = [\n ...(state.bindingRetries ?? []).filter(\n (entry) => entry.submissionId !== selected.submissionId,\n ),\n ...(retry === undefined ? [] : [retry]),\n ];\n\n yield* transaction.put(\n MAINTENANCE_STATE_KEY,\n yield* Schema.encodeEffect(ThreadMaintenanceState)(\n ThreadMaintenanceState.make({ ...state, bindingRetries }),\n ),\n );\n }),\n )\n .pipe(Effect.mapError(alarmFailure(\"record submission binding retry\"))),\n );\n yield* failpoint.hit(\"maintenance:binding-retry:after\");\n }\n if (bindingFailure !== undefined) {\n yield* reportBindingFailure\n ? Effect.logError(\n \"Thread awaits a current agent binding; original work remains pending\",\n Cause.fail(bindingFailure),\n )\n : Effect.logDebug(\"Thread binding retry remains pending\", Cause.fail(bindingFailure));\n }\n\n return Option.isSome(settlement) ? 1 : 0;\n });\n\n const advance = Effect.fn(\"ThreadMaintenance.advance\")(function* (\n started: Effect.Success<ReturnType<typeof beginNative>>,\n yieldAfter: DateTime.Utc,\n observed: MaintenanceObservation,\n recovery: NativeRecovery,\n native: NativeDispatch,\n dispatch = true,\n reserved: ReadonlySet<ThreadId> = new Set(native.active.keys()),\n ): Effect.fn.Return<NativePassResult, MaintenancePassFailure> {\n const deadline = yield* publication.pendingDeadline;\n\n if (\n started._tag === \"Actionable\" ||\n (Option.isSome(deadline) && deadline.value <= (yield* Clock.currentTimeMillis))\n ) {\n yield* publication.drain;\n }\n const pending = yield* publication.pendingDeadline;\n\n if (started._tag === \"CaughtUp\" || Option.isSome(pending)) {\n const nextAttemptAt = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n\n const { state } = yield* runTransaction(\"read native maintenance deadline\", () =>\n ctx.storage.transaction((transaction) => readMaintenanceState(transaction)),\n );\n\n const native =\n active > 0 || state.dirty > state.processed\n ? state.retry?.generation === state.dirty && active === 0\n ? state.retry.notBefore\n : now + minimumAlarmDelay\n : Infinity;\n\n const next = Option.isSome(pending) ? pending.value : native;\n\n return Number.isFinite(next) ? Math.max(now + minimumAlarmDelay, next) : undefined;\n }),\n );\n\n return {\n phase: \"caught-up\",\n nonterminal: started.nonterminal,\n nextAttemptAt,\n };\n }\n if (native.generation !== started.generation) {\n native.deferred.clear();\n native.generation = started.generation;\n }\n // A stable generation with no freed slot needs no second ledger/history scan.\n // Enrollment precedes admission: never cache a scan overlapping a producer body,\n // which may make a head ready later without another generation increment.\n if (native.active.size > 0 && native.scanGeneration === started.generation) {\n return {\n phase: \"actionable\",\n nonterminal: started.nonterminal,\n nextAttemptAt: undefined,\n };\n }\n native.scanGeneration = started.activeAtStart === 0 ? started.generation : undefined;\n\n // Select from control state before reading execution history. A recovering or faulted\n // Thread cannot enter dispatch; old cleanup has its own scoped opportunity below.\n observed.nativeOnly = true;\n\n // Every checkpoint keeps the producer overlap that belongs to this recovery wave.\n const observation = (recovery.observation ??= {\n generation: started.generation,\n activeAtStart: started.activeAtStart,\n });\n\n const current = yield* Stream.runCollect(ledger.scanNonterminal);\n const selectionTime = yield* Clock.currentTimeMillis;\n\n yield* runTransaction(\"read Thread recovery deadlines\", async () => {\n for (const threadId of new Set(current.map((row) => row.threadId))) {\n if (recovery.loaded.has(threadId)) continue;\n const encoded = await ctx.storage.get(recoveryFaultKey(threadId));\n\n if (encoded !== undefined)\n recovery.faults.set(threadId, decodeRecoveryFault(threadId, encoded));\n recovery.loaded.add(threadId);\n }\n });\n const reports = recovery.reports;\n const recoveryFaults = recovery.faults;\n\n const waiting = (row: SubmissionWorkItem) =>\n !recovery.pending.has(row.threadId) &&\n !recoveryFaults.has(row.threadId) &&\n stableExternalWait(row, reports);\n\n const heads = new Map<ThreadId, SubmissionWorkItem>();\n\n for (const row of current) {\n // Only recovered uncertainty may release later input; accepted aborts retain FIFO.\n if (row.state === \"unknown\" && waiting(row)) continue;\n if (!heads.has(row.threadId)) heads.set(row.threadId, row);\n }\n const stopping = new Set<ThreadId>();\n\n for (const head of heads.values()) {\n if (\n head.state !== \"ready\" ||\n native.active.has(head.threadId) ||\n recovery.pending.has(head.threadId) ||\n recoveryFaults.has(head.threadId)\n )\n continue;\n\n // An accepted abort is cleanup even when its input was never claimed. This\n // control-only read must not decode the execution journal or a recovery snapshot.\n const intent = yield* isolateRecovery(\n ledger.readAbortIntent(AbortIntentRequest.make({ submissionId: head.submissionId })),\n {\n timeout: recoveryConfig.recoveryTimeout,\n phase: () => \"recovery\",\n operation: \"read abort intent\",\n },\n );\n\n if (Result.isSuccess(intent)) {\n if (intent.success !== undefined) stopping.add(head.threadId);\n } else {\n const faults = yield* recordRecoveryStatus(\n RecoverySweepResult.make({\n reports: [],\n blocked: [\n RecoveryBlocked.make({ threadId: head.threadId, failure: intent.failure }),\n ],\n }),\n );\n\n for (const [threadId, fault] of faults) recoveryFaults.set(threadId, fault);\n recovery.recovered++;\n }\n }\n\n const eligible = [...heads.values()]\n .filter(\n (head) =>\n !recovery.pending.has(head.threadId) &&\n !stopping.has(head.threadId) &&\n !recoveryFaults.has(head.threadId) &&\n !waiting(head) &&\n (head.state === \"ready\" || reports.has(head.submissionId)),\n )\n .map((head) => head.threadId)\n .sort();\n\n yield* failpoint.hit(\"maintenance:select:before\");\n\n const selection = yield* runTransaction(\"select maintenance lane\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const retries = (state.bindingRetries ?? []).filter(\n (retry) => heads.get(retry.threadId)?.submissionId === retry.submissionId,\n );\n\n const runnable = eligible.filter(\n (threadId) =>\n !reserved.has(threadId) &&\n !native.active.has(threadId) &&\n !native.deferred.has(threadId) &&\n !retries.some(\n (retry) => retry.threadId === threadId && retry.notBefore > selectionTime,\n ),\n );\n\n const pivot = Math.max(\n 0,\n runnable.findIndex(\n (threadId) =>\n state.lastServedThreadId === undefined || threadId > state.lastServedThreadId,\n ),\n );\n\n const selected = dispatch\n ? [...runnable.slice(pivot), ...runnable.slice(0, pivot)].slice(\n 0,\n nativeDispatchConcurrency - reserved.size,\n )\n : [];\n\n const next = selected.at(-1);\n\n if (next !== undefined) {\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(\n ThreadMaintenanceState.make({ ...state, lastServedThreadId: next }),\n ),\n );\n }\n\n const backlog = recovery.started\n ? []\n : [...heads.keys()].filter((threadId) => {\n const fault = recoveryFaults.get(threadId);\n\n return (\n !eligible.includes(threadId) &&\n (fault === undefined || fault.retryAt <= selectionTime)\n );\n });\n\n // One finite wave, one Thread at a time, with the runtime's per-Thread deadline.\n // This cursor ensures an event deadline/eviction cannot always restart at the front.\n const after = backlog.filter(\n (threadId) =>\n state.lastRecoveredThreadId === undefined || threadId > state.lastRecoveredThreadId,\n );\n\n const before = backlog.filter(\n (threadId) =>\n state.lastRecoveredThreadId !== undefined &&\n threadId <= state.lastRecoveredThreadId,\n );\n\n return { selected, retries, backlog: [...after, ...before] };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:select:after\");\n if (!recovery.started) {\n recovery.started = true;\n recovery.needsCheckpoint = selection.backlog.length > 0;\n for (const threadId of selection.backlog) recovery.pending.add(threadId);\n yield* Deferred.succeed(recovery.queue, selection.backlog);\n }\n\n for (const threadId of selection.selected) {\n const selected = heads.get(threadId);\n\n if (selected === undefined) continue;\n // Reserve before recovery or claim acquisition. The durable Claim remains the\n // authority; this event-local reservation only prevents duplicate dispatch.\n native.dispatched++;\n native.active.set(\n threadId,\n yield* Effect.forkIn(\n attemptSelected(selected, selection.retries, yieldAfter, recovery),\n native.scope,\n ),\n );\n }\n\n if (native.active.size > 0) {\n // Active Attempts own their claims and may still append/settle. Only acknowledge\n // a generation after joining every admitted native Attempt.\n return {\n phase: \"actionable\",\n nonterminal: current.length,\n nextAttemptAt: undefined,\n dispatched: selection.selected.length > 0,\n };\n }\n const retries = selection.retries;\n\n const remaining = yield* Stream.runCollect(ledger.scanNonterminal);\n const waitingHeads = new Map<ThreadId, boolean>();\n\n const autonomous = remaining.some((snapshot) => {\n if (snapshot.state === \"unknown\" && waiting(snapshot)) return false;\n const headWaiting = waitingHeads.get(snapshot.threadId);\n\n if (headWaiting === undefined) waitingHeads.set(snapshot.threadId, waiting(snapshot));\n // FIFO followers cannot execute through a stable external wait. Only plain queued\n // input is dormant here; admission repairs and accepted aborts still need a pass.\n if (\n headWaiting === true &&\n snapshot.state === \"ready\" &&\n reports.get(snapshot.submissionId)?.decision._tag === \"ApplyInput\"\n )\n return false;\n\n return !waiting(snapshot);\n });\n\n const progressed = native.progressed || recovery.repaired;\n\n const now = yield* Clock.currentTimeMillis;\n const ordinaryDelay = autonomous ? yield* rearmDelay(progressed, started.stalls) : 0;\n\n const nextEligible = [...recoveryFaults.values()]\n .map((fault) => fault.retryAt)\n .concat(\n eligible.map(\n (threadId) =>\n retries.find((retry) => retry.submissionId === heads.get(threadId)?.submissionId)\n ?.notBefore ?? now,\n ),\n );\n\n const retryDelay =\n nextEligible.length === 0 ? 0 : Math.max(0, Math.min(...nextEligible) - now);\n\n const delay = Math.max(ordinaryDelay, retryDelay);\n\n // Checkpoint native progress without changing the physical alarm. Auxiliary\n // delivery remains live; later mutations still advance the shared generation.\n yield* failpoint.hit(\"maintenance:checkpoint:before\");\n\n const nextAttemptAt = yield* mutations.withSnapshot((active) =>\n runTransaction(\"checkpoint native maintenance\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const mutationOverlap =\n observation.activeAtStart > 0 || started.activeAtStart > 0 || active > 0;\n\n // An empty control scan needs no older recovery report. Certify its fresh\n // snapshot only when no producer overlapped it or advanced the generation.\n const generation =\n remaining.length === 0 && !mutationOverlap && state.dirty === started.generation\n ? started.generation\n : observation.generation;\n\n const processed =\n autonomous || mutationOverlap\n ? state.processed\n : state.processed > generation\n ? state.processed\n : generation;\n\n // Enrollment precedes the mutation body. A retry from an overlapping snapshot\n // must not defer work that becomes ready later in that same generation.\n const canBackoff = !mutationOverlap && state.dirty === started.generation;\n\n const next = ThreadMaintenanceState.make({\n ...Struct.omit(state, [\"retry\"]),\n processed,\n nonterminal: remaining.length,\n bindingRetries: (state.bindingRetries ?? []).filter((retry) =>\n remaining.some((row) => row.submissionId === retry.submissionId),\n ),\n ...(autonomous && !progressed && canBackoff\n ? {\n retry: MaintenanceRetry.make({\n generation: started.generation,\n notBefore: now + delay,\n nativeOnly: true,\n stalls: Math.min(30, started.stalls + 1),\n }),\n }\n : {}),\n });\n\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n if (autonomous) {\n return now + (canBackoff ? delay : minimumAlarmDelay);\n }\n\n return mutationOverlap || next.dirty > next.processed\n ? now + minimumAlarmDelay\n : undefined;\n }),\n ),\n );\n\n yield* failpoint.hit(\"maintenance:checkpoint:after\");\n native.deferred.clear();\n native.progressed = false;\n native.needsCheckpoint = false;\n\n return {\n phase: \"actionable\",\n nonterminal: remaining.length,\n nextAttemptAt,\n };\n });\n\n const pass = Effect.fn(\"ThreadMaintenance.pass\")(function* (\n yieldAfter: DateTime.Utc,\n dispatchUntil: DateTime.Utc,\n observed: MaintenanceObservation,\n ): Effect.fn.Return<MaintenancePassReport, MaintenancePassFailure, Scope.Scope> {\n // Subscribe before the first native snapshot. Hints accelerate rechecks; the\n // bounded scan and durable generation still recover dropped notifications.\n const notified = (yield* Stream.toPull(wakes.wakes)).pipe(\n Effect.asVoid,\n Effect.catch(() => Effect.never),\n );\n\n // A wake may observe temporary backoff while this event's recovery is still running.\n // Its completion must retain the original actionable observation for acknowledgement.\n const started = yield* beginNative(observed);\n\n // This scope owns every admitted finite wave, including native advancement.\n // Close it before final alarm rearming, including on failure or event interruption.\n const auxiliaryScope = yield* Effect.acquireRelease(Scope.make(\"parallel\"), (scope, exit) =>\n Scope.close(scope, exit),\n );\n\n const fork = <A, E>(work: Effect.Effect<A, E>) => Effect.forkIn(work, auxiliaryScope);\n\n // Each lane has at most one finite wave. A completion is retained until the single\n // scheduling loop observes it; a busy sibling cannot consume another lane's hint.\n const lanes = host.lanes.map((lane) => ({\n ...lane,\n initial: true,\n check: true,\n exhausted: false,\n fiber: undefined as Fiber.Fiber<boolean, DurableAlarmError> | undefined,\n }));\n\n let messageExhausted = false;\n let delivery: Fiber.Fiber<void, DurableAlarmError> | undefined;\n let failure: Cause.Cause<MaintenancePassFailure> | undefined;\n\n const recovery: NativeRecovery = {\n queue: yield* Deferred.make<ReadonlyArray<ThreadId>>(),\n pending: new Set(),\n loaded: new Set(),\n reports: new Map(),\n faults: new Map(),\n started: false,\n needsCheckpoint: false,\n recovered: 0,\n repaired: false,\n };\n\n const recoveryFiber = yield* fork(\n Effect.gen(function* () {\n for (const threadId of yield* Deferred.await(recovery.queue)) {\n yield* failpoint.hit(\"maintenance:select:before\");\n yield* runTransaction(\"select old recovery lane\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(\n ThreadMaintenanceState.make({ ...state, lastRecoveredThreadId: threadId }),\n ),\n );\n }),\n );\n yield* failpoint.hit(\"maintenance:select:after\");\n yield* recoverThread(threadId, recovery);\n recovery.pending.delete(threadId);\n yield* wakes.notify(threadId);\n }\n }),\n );\n\n // Backfill is one disposable wave; native and host work keep their own opportunities.\n const backfill = yield* fork(\n drainDue.pipe(\n Effect.provideService(ThreadProjectionMaintenance, projection),\n Effect.timeoutOption(config.projectionDispatchTimeoutMillis),\n ),\n );\n\n let backfillObserved = false;\n let recoveryObserved = false;\n\n const dispatch: NativeDispatch = {\n scope: auxiliaryScope,\n active: new Map(),\n deferred: new Set(),\n dispatched: 0,\n settled: 0,\n progressed: false,\n needsCheckpoint: false,\n };\n\n let native: Fiber.Fiber<NativePassResult, MaintenancePassFailure> | undefined = yield* fork(\n advance(started, yieldAfter, observed, recovery, dispatch),\n );\n\n let result: NativePassResult = {\n phase: \"caught-up\",\n nonterminal: started.nonterminal,\n nextAttemptAt: undefined,\n };\n\n let phase = result.phase;\n let nativeCheck = false;\n const until = DateTime.toEpochMillis(yieldAfter);\n const dispatchEnd = DateTime.toEpochMillis(dispatchUntil);\n\n const checkLanes = () => {\n for (const lane of lanes) lane.check = true;\n };\n\n while (true) {\n if (native?.pollUnsafe() !== undefined) {\n result = yield* Fiber.join(native);\n native = undefined;\n if (result.phase === \"actionable\") phase = \"actionable\";\n observed.nativeOnly = dispatch.active.size > 0;\n if (result.dispatched === true && dispatch.active.size < nativeDispatchConcurrency) {\n dispatch.scanGeneration = undefined;\n nativeCheck = true;\n }\n // An empty initial scan still opens exactly one old-recovery opportunity.\n recovery.started = true;\n yield* Deferred.succeed(recovery.queue, []);\n checkLanes();\n }\n for (const [threadId, attempt] of dispatch.active) {\n const exit = attempt.pollUnsafe();\n\n if (exit === undefined) continue;\n dispatch.active.delete(threadId);\n dispatch.scanGeneration = undefined;\n if (Exit.isFailure(exit)) return yield* Effect.failCause(exit.cause);\n dispatch.settled += exit.value;\n dispatch.progressed ||= exit.value > 0;\n dispatch.needsCheckpoint = true;\n if (exit.value === 0) dispatch.deferred.add(threadId);\n nativeCheck = true;\n checkLanes();\n }\n if (!recoveryObserved && recoveryFiber.pollUnsafe() !== undefined) {\n yield* Fiber.join(recoveryFiber);\n recoveryObserved = true;\n dispatch.scanGeneration = undefined;\n nativeCheck ||= recovery.needsCheckpoint;\n }\n if (!backfillObserved) {\n const exit = backfill.pollUnsafe();\n\n if (exit !== undefined) {\n backfillObserved = true;\n if (Exit.isFailure(exit)) failure ??= exit.cause;\n }\n }\n for (const lane of lanes) {\n const exit = lane.fiber?.pollUnsafe();\n\n if (exit === undefined) continue;\n lane.fiber = undefined;\n if (Exit.isFailure(exit)) {\n failure ??= exit.cause;\n lane.exhausted = true;\n } else {\n lane.check ||= exit.value;\n }\n }\n const deliveryExit = delivery?.pollUnsafe();\n\n if (deliveryExit !== undefined) {\n delivery = undefined;\n if (Exit.isFailure(deliveryExit)) {\n failure ??= deliveryExit.cause;\n messageExhausted = true;\n }\n }\n\n // A failed auxiliary lane is exhausted for this event. Its error must not\n // retire healthy admission, delivery or native work that still has an allowance.\n const now = yield* Clock.currentTimeMillis;\n\n if (now >= until) break;\n\n for (const lane of lanes) {\n if (lane.fiber !== undefined || lane.exhausted || !lane.check) continue;\n lane.check = false;\n lane.fiber = yield* fork(\n Effect.gen(function* () {\n yield* Schema.decodeEffect(AuxiliaryDispatchMillis)(\n lane.dispatchTimeoutMillis,\n ).pipe(\n Effect.mapError((cause) =>\n DurableAlarmError.make({\n operation: \"host dispatch allowance\",\n message:\n \"Declare an integer whole-wave allowance between 1 and 300000 milliseconds\",\n cause,\n }),\n ),\n );\n if ((yield* Clock.currentTimeMillis) + lane.dispatchTimeoutMillis > dispatchEnd) {\n lane.exhausted = true;\n\n return false;\n }\n\n return yield* Effect.gen(function* () {\n if (!lane.initial) {\n const deadline = yield* lane.pendingDeadline;\n\n if (\n Option.isNone(deadline) ||\n deadline.value > (yield* Clock.currentTimeMillis)\n )\n return false;\n }\n const selectedAt = yield* Clock.currentTimeMillis;\n\n if (\n selectedAt >= until ||\n selectedAt + lane.dispatchTimeoutMillis > dispatchEnd\n ) {\n lane.exhausted = true;\n\n return false;\n }\n lane.initial = false;\n yield* lane.run;\n\n return true;\n }).pipe(\n // Cleanup shares this wave's original allowance.\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: lane.dispatchTimeoutMillis,\n orElse: () =>\n DurableAlarmError.make({\n operation: \"host dispatch allowance\",\n message:\n \"The admitted host wave exceeded its allowance; durable work remains pending\",\n }),\n }),\n );\n }),\n );\n }\n if (delivery === undefined && !messageExhausted) {\n // Selection is bounded local work. Fork only an actual due wave, so an empty\n // deadline check cannot extend retirement or consume another scheduling turn.\n const selected = yield* Effect.gen(function* () {\n const deadline = yield* messages.pendingDeadline;\n\n return Option.isSome(deadline) && deadline.value <= (yield* Clock.currentTimeMillis)\n ? Option.some(yield* messages.prepare)\n : Option.none();\n }).pipe(Effect.exit);\n\n if (Exit.isFailure(selected)) {\n failure ??= selected.cause;\n messageExhausted = true;\n } else if (Option.isSome(selected.value)) {\n const wave = selected.value.value;\n const selectedAt = yield* Clock.currentTimeMillis;\n\n if (selectedAt >= until || selectedAt + wave.timeoutMillis > dispatchEnd) {\n messageExhausted = true;\n } else {\n // No second timeout: the driver owes the Claim's timeout/retry commit.\n delivery = yield* fork(wave.run);\n }\n }\n }\n\n // Retire a quiet event before consuming hints queued during its native Attempt.\n // Recovery still gets its checkpoint and, if needed, initial dispatch opportunity.\n if (\n native === undefined &&\n dispatch.active.size === 0 &&\n recoveryObserved &&\n !recovery.needsCheckpoint &&\n backfillObserved &&\n delivery === undefined &&\n lanes.every((lane) => lane.fiber === undefined)\n )\n break;\n\n if (\n native === undefined &&\n nativeCheck &&\n dispatch.active.size < nativeDispatchConcurrency\n ) {\n nativeCheck = false;\n const nativeCheckpoint = dispatch.needsCheckpoint && dispatch.active.size === 0;\n const checkpoint = (recoveryObserved && recovery.needsCheckpoint) || nativeCheckpoint;\n\n if (checkpoint) recovery.needsCheckpoint = false;\n // Keep this opportunity's reservations across beginNative's storage awaits.\n // A finishing Attempt cannot turn a refill into another same-Thread Attempt.\n const reserved = new Set(dispatch.active.keys());\n\n native = yield* fork(\n Effect.gen(function* () {\n const awakened = checkpoint ? started : yield* beginNative(observed);\n\n return yield* advance(\n awakened,\n yieldAfter,\n observed,\n recovery,\n dispatch,\n !nativeCheckpoint && (!checkpoint || dispatch.settled === 0),\n reserved,\n );\n }),\n );\n }\n\n const next = Math.min(\n native === undefined ? (result.nextAttemptAt ?? Infinity) : Infinity,\n now + config.wakeScanInterval,\n until,\n );\n\n const completing = [\n ...(native === undefined ? [] : [native]),\n ...dispatch.active.values(),\n ...(recoveryObserved ? [] : [recoveryFiber]),\n ...(backfillObserved ? [] : [backfill]),\n ...(delivery === undefined ? [] : [delivery]),\n ...lanes.flatMap((lane) => (lane.fiber === undefined ? [] : [lane.fiber])),\n ];\n\n const ready = yield* Effect.raceAllFirst([\n ...completing.map((fiber) =>\n Fiber.await<unknown, MaintenancePassFailure>(fiber).pipe(\n Effect.as(\"completed\" as const),\n ),\n ),\n Effect.raceFirst(notified, Effect.sleep(Math.max(0, next - now))).pipe(\n Effect.as(\"scan\" as const),\n ),\n ]);\n\n if (ready === \"scan\") {\n nativeCheck = true;\n checkLanes();\n }\n }\n // Dispatch is closed. Join each admitted wave without renewing its allowance.\n // Message Claims retain their driver's own timer and local retry commit.\n if (native !== undefined) {\n result = yield* Fiber.join(native);\n if (result.phase === \"actionable\") phase = \"actionable\";\n observed.nativeOnly = dispatch.active.size > 0;\n recovery.started = true;\n yield* Deferred.succeed(recovery.queue, []);\n }\n for (const attempt of dispatch.active.values()) {\n const settled = yield* Fiber.join(attempt);\n\n dispatch.settled += settled;\n dispatch.progressed ||= settled > 0;\n }\n dispatch.active.clear();\n observed.nativeOnly = false;\n for (const fiber of [\n recoveryFiber,\n backfill,\n ...(delivery === undefined ? [] : [delivery]),\n ...lanes.flatMap((lane) => (lane.fiber === undefined ? [] : [lane.fiber])),\n ]) {\n // Await exits without failing fast: every admitted wave owns its original\n // bounded allowance and cleanup even if another wave has already failed.\n const exit = yield* Fiber.await<unknown, MaintenancePassFailure>(fiber);\n\n if (Exit.isFailure(exit)) failure ??= exit.cause;\n }\n if (failure !== undefined) return yield* Effect.failCause(failure);\n if (recovery.needsCheckpoint || dispatch.dispatched > 0) {\n result = yield* advance(started, yieldAfter, observed, recovery, dispatch, false);\n if (result.phase === \"actionable\") phase = \"actionable\";\n }\n yield* Scope.close(auxiliaryScope, Exit.void);\n yield* failpoint.hit(\"maintenance:finish:before\");\n\n const disposition = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n const latest = yield* pendingDeadline;\n const now = yield* Clock.currentTimeMillis;\n\n return yield* runTransaction(\"finish maintenance event\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const native =\n active > 0 || state.dirty > state.processed\n ? state.retry?.generation === state.dirty && active === 0\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : state.dirty === observed.generation && active === 0\n ? (result.nextAttemptAt ?? now + config.wakeScanInterval)\n : now + minimumAlarmDelay\n : Infinity;\n\n const next = Option.isSome(latest) ? Math.min(native, latest.value) : native;\n\n if (Number.isFinite(next)) {\n await transaction.setAlarm(Math.max(now + minimumAlarmDelay, next));\n\n return \"rearmed\" as const;\n }\n await transaction.deleteAlarm();\n\n return \"cleared\" as const;\n }),\n );\n }),\n );\n\n yield* failpoint.hit(\"maintenance:finish:after\");\n\n const report = MaintenancePassReport.make({\n phase,\n recovered: recovery.recovered,\n settled: dispatch.settled,\n nonterminal: result.nonterminal,\n alarm: disposition,\n });\n\n yield* Effect.annotateCurrentSpan({\n phase: report.phase,\n recovered: report.recovered,\n settled: report.settled,\n nonterminal: report.nonterminal,\n alarm: report.alarm,\n });\n\n return report;\n });\n\n return ThreadMaintenance.of({\n // A mid-pass immediate hint is droppable; durable dirty state decides the final alarm.\n pass: Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const yieldAfter = DateTime.makeUnsafe(now + 10 * 60_000);\n const dispatchUntil = DateTime.makeUnsafe(now + 14 * 60_000);\n const observed: MaintenanceObservation = { nativeOnly: false };\n\n return yield* alarm.withWakesDeferred(\n maintenancePassGate.withPermit(\n Effect.scoped(pass(yieldAfter, dispatchUntil, observed)).pipe(\n // Close event-owned auxiliary work and release Attempt ownership before\n // failure rearming, while still holding the pass permit.\n Effect.onErrorIf(\n () => true,\n () => rearmFailure(observed),\n ),\n ),\n ),\n );\n }).pipe(\n // Include permit waiting, recovery and acknowledgement in the event deadline.\n // Interruption releases Attempt ownership, leaving the prearmed dirty generation\n // for recovery. It never changes the logical Run duration or settles a policy failure.\n // This cooperative timer cannot preempt synchronous CPU work or stuck finalizers.\n Effect.timeoutOrElse({\n duration: \"14 minutes\",\n orElse: () =>\n DurableAlarmError.make({\n operation: \"maintenance pass deadline\",\n message:\n \"The maintenance event exceeded its 14 minute deadline; durable recovery remains pending\",\n }),\n }),\n ),\n ensureAlarm: mutations.withSnapshot(() => ensureAlarm()),\n recoveryStatus,\n withMutation: (body) =>\n mutations.withMutation(\n body.pipe(\n Effect.tap(() =>\n publishCommitted.pipe(Effect.provideService(ThreadPublication, publication)),\n ),\n ),\n ),\n });\n }),\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.132","dependencies":{"@effect-agent/storage-cloudflare":"0.1.0-beta.132","@effect/platform-browser":"4.0.0-rc.116","@effect/sql-sqlite-do":"4.0.0-rc.116","effect-agent":"0.1.0-beta.132","puppeteer-core":"24.29.0"},"devDependencies":{"@cloudflare/vitest-pool-workers":"0.21.3","@cloudflare/workers-types":"5.20260825.1","@effect-agent/testing":"0.1.0-beta.132","@effect/platform-node":"4.0.0-rc.116","@effect/sql-d1":"4.0.0-rc.116","@effect/vitest":"4.0.0-rc.116","effect":"4.0.0-rc.116","effect-cf":"0.44.1","esbuild":"0.28.1","miniflare":"5.20260811.1-alpha","typescript":"7.0.2","vite-plus":"0.3.2","vitest":"4.1.11"},"peerDependencies":{"effect":"^4.0.0-rc.116","effect-cf":"^0.44.1 || ^0.45.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./alarm":{"types":"./dist/Alarm.d.mts","default":"./dist/Alarm.mjs"},"./browser-rest-capture":{"types":"./dist/BrowserRestCapture.d.mts","default":"./dist/BrowserRestCapture.mjs"},"./browser-rest-crawl":{"types":"./dist/BrowserRestCrawl.d.mts","default":"./dist/BrowserRestCrawl.mjs"},"./cloudflare-bindings":{"types":"./dist/CloudflareBindings.d.mts","default":"./dist/CloudflareBindings.mjs"},"./cloudflare-browser":{"types":"./dist/CloudflareBrowser.d.mts","default":"./dist/CloudflareBrowser.mjs"},"./cloudflare-code-mode":{"types":"./dist/CloudflareCodeMode.d.mts","default":"./dist/CloudflareCodeMode.mjs"},"./cloudflare-config":{"types":"./dist/CloudflareConfig.d.mts","default":"./dist/CloudflareConfig.mjs"},"./cloudflare-memory":{"types":"./dist/CloudflareMemory.d.mts","default":"./dist/CloudflareMemory.mjs"},"./cloudflare-scheduling":{"types":"./dist/CloudflareScheduling.d.mts","default":"./dist/CloudflareScheduling.mjs"},"./cloudflare-subscriptions":{"types":"./dist/CloudflareSubscriptions.d.mts","default":"./dist/CloudflareSubscriptions.mjs"},"./cloudflare-thread-client":{"types":"./dist/CloudflareThreadClient.d.mts","default":"./dist/CloudflareThreadClient.mjs"},"./interactive-browser":{"types":"./dist/InteractiveBrowser.d.mts","default":"./dist/InteractiveBrowser.mjs"},"./browser-session":{"types":"./dist/BrowserSession.d.mts","default":"./dist/BrowserSession.mjs"},"./browser-credentials":{"types":"./dist/BrowserCredentials.d.mts","default":"./dist/BrowserCredentials.mjs"},"./thread-object":{"types":"./dist/ThreadObject.d.mts","default":"./dist/ThreadObject.mjs"},"./wake-scheduler":{"types":"./dist/WakeScheduler.d.mts","default":"./dist/WakeScheduler.mjs"},"./cloudflare-ai-gateway":{"types":"./dist/CloudflareAiGateway.d.mts","default":"./dist/CloudflareAiGateway.mjs"}},"description":"Cloudflare Layer assembly for Effect Agent: Durable Objects and Browser Run adapters.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/platform-cloudflare"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json"}}
|
package/src/Alarm.ts
CHANGED
|
@@ -1433,12 +1433,19 @@ export class ThreadMaintenance extends Context.Service<
|
|
|
1433
1433
|
const mutationOverlap =
|
|
1434
1434
|
observation.activeAtStart > 0 || started.activeAtStart > 0 || active > 0;
|
|
1435
1435
|
|
|
1436
|
+
// An empty control scan needs no older recovery report. Certify its fresh
|
|
1437
|
+
// snapshot only when no producer overlapped it or advanced the generation.
|
|
1438
|
+
const generation =
|
|
1439
|
+
remaining.length === 0 && !mutationOverlap && state.dirty === started.generation
|
|
1440
|
+
? started.generation
|
|
1441
|
+
: observation.generation;
|
|
1442
|
+
|
|
1436
1443
|
const processed =
|
|
1437
1444
|
autonomous || mutationOverlap
|
|
1438
1445
|
? state.processed
|
|
1439
|
-
: state.processed >
|
|
1446
|
+
: state.processed > generation
|
|
1440
1447
|
? state.processed
|
|
1441
|
-
:
|
|
1448
|
+
: generation;
|
|
1442
1449
|
|
|
1443
1450
|
// Enrollment precedes the mutation body. A retry from an overlapping snapshot
|
|
1444
1451
|
// must not defer work that becomes ready later in that same generation.
|