Merge qualified recovery grouping and prerequisites

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* commit '2aa0179c35564fae529eb8053f0ed098f60dcc64':
  Preserve native receipt grouping within each bounded worker pass
This commit is contained in:
DottaandPaperclip committed 2026-10-31 00:06:47 -05:00
commit 0b081d9ffe
5 files changed
+197 -27

No files matched your search

+1 -1
View File
@@ -4214,7 +4214,7 @@ export function heartbeatService(
registerDeferredReceiptWork(db, coordinator, {
resume: scope => heartbeatQueue.resumeDeferredExecutionReceipts(scope),
settleTaskChat: scope => reconcileTaskChatRetryReceipts(db, { ...scope, settleOnly: true }),
dispatchNative: dispatchPendingNativeStatusWakeups,
createNativeBatch: heartbeatQueue.createNativeStatusWakeBatch,
schedulingSuppressed: async () => (await getSchedulingSuppression(true)).suppressed,
}, () => canRun() && readTaskDrain(new Date()) === null),
registerIssueStateRecoveryWork: (coordinator: Parameters<typeof registerIssueRecoveryWork>[1], canRun: () => boolean) =>
@@ -18,7 +18,7 @@ export function registerDeferredReceiptWork(
owner: {
resume(scope: DeferredReceiptRecoveryOptions): Promise<unknown>;
settleTaskChat(scope: DeferredExecutionScope): Promise<unknown>;
dispatchNative(scope: NativeIntentOptions): Promise<unknown>;
createNativeBatch(): (scope: NativeIntentOptions) => Promise<unknown>;
schedulingSuppressed(): Promise<boolean>;
},
canRun: () => boolean,
@@ -26,12 +26,17 @@ export function registerDeferredReceiptWork(
function register(kind: "deferred" | "task_chat" | "native") {
const cursors = new Map<string, string>();
let enabled = false;
let dispatchNative: ReturnType<typeof owner.createNativeBatch>;
const queue = kind === "deferred" ? DELIVERY_QUEUES.deferredExecutionReceipts
: kind === "task_chat" ? DELIVERY_QUEUES.taskRetryReceiptSettlement : DELIVERY_QUEUES.nativeStatusWakeIntents;
return registerScopedDeadlineWork<Entry, DeferredExecutionScope>(coordinator, {
queue,
batchSize: kind === "native" ? 100 : undefined,
reconstructionIntervalMs: 30_000,
beforePass: async () => { enabled = !(await owner.schedulingSuppressed()); },
beforePass: async () => {
enabled = !(await owner.schedulingSuppressed());
if (kind === "native") dispatchNative = owner.createNativeBatch();
},
decodeScope: hint => hint === "*" ? undefined : JSON.parse(hint),
matches: (entry, scope) => !scope || entry.companyId === scope.companyId && (!scope.requestId || entry.id === scope.requestId),
load: async scope => {
@@ -101,7 +106,7 @@ export function registerDeferredReceiptWork(
const errors: unknown[] = [];
let next: number | null = null;
const scope = { companyId: entry.companyId, requestId: entry.id };
if (kind === "native") await owner.dispatchNative({ ...scope,
if (kind === "native") await dispatchNative({ ...scope,
onDeferredDeadline: at => { next = next === null ? at : Math.min(next, at); },
onError: error => { errors.push(error); },
});
+22 -13
View File
@@ -4779,15 +4779,27 @@ export function createHeartbeatQueue(db: Db, dependencies: HeartbeatQueueDepende
* wake was inserted but before the intent was linked to it. Dispatch failure
* only requeues the intent; it never changes the provider run outcome.
*/
async function dispatchPendingNativeStatusWakeups(
input: {
companyId?: string;
limit?: number;
staleClaimMs?: number;
requestId?: string;
onDeferredDeadline?: (at: number) => void;
onError?: (error: unknown) => void;
} = {},
type NativeStatusWakeDispatchInput = {
companyId?: string;
limit?: number;
staleClaimMs?: number;
requestId?: string;
onDeferredDeadline?: (at: number) => void;
onError?: (error: unknown) => void;
};
type NativeStatusWakeDelivery = { runId: string | null; status: string };
function createNativeStatusWakeBatch() {
const deliveredByIssueScope = new Map<string, NativeStatusWakeDelivery>();
return (input: NativeStatusWakeDispatchInput = {}) => dispatchNativeStatusWakeBatch(input, deliveredByIssueScope);
}
function dispatchPendingNativeStatusWakeups(input: NativeStatusWakeDispatchInput = {}) {
return createNativeStatusWakeBatch()(input);
}
async function dispatchNativeStatusWakeBatch(input: NativeStatusWakeDispatchInput,
deliveredByIssueScope: Map<string, NativeStatusWakeDelivery>,
) {
const now = new Date();
const staleClaimMs = Math.max(1_000, input.staleClaimMs ?? 60_000);
@@ -4812,10 +4824,6 @@ export function createHeartbeatQueue(db: Db, dependencies: HeartbeatQueueDepende
let dispatched = 0;
let recovered = 0;
let deferred = 0;
const deliveredByIssueScope = new Map<
string,
{ runId: string | null; status: string }
>();
for (const candidate of candidates) {
const payload = parseObject(candidate.payload);
@@ -5088,6 +5096,7 @@ export function createHeartbeatQueue(db: Db, dependencies: HeartbeatQueueDepende
return {
enqueueWakeup,
dispatchPendingNativeStatusWakeups,
createNativeStatusWakeBatch,
startNextQueuedRunForAgent,
countRunningRunsForAgent,
releaseRunClaimedJustBeforeSuppression,