FN-6177: remove queued-concurrency scheduler audit
Remove the write-only queued-concurrency scheduler audit and its stale documentation. - delete scheduler:dispatch-queued-concurrency audit emission and memo bookkeeping - keep queued concurrency log dedupe coverage while removing audit-specific scheduler test assertions - update architecture docs to describe queued concurrency diagnostics as log output only Files changed: docs/architecture.md | 4 +- packages/engine/src/__tests__/scheduler.test.ts | 33 ---------------- packages/engine/src/scheduler.ts | 51 ------------------------- 3 files changed, 2 insertions(+), 86 deletions(-) Fusion-Task-Id: FN-6177 Fusion-Task-Lineage: e4516b41-5525-4e26-9602-772302d63f3d
This commit is contained in:
@@ -1834,12 +1834,6 @@ describe("Scheduler", () => {
|
||||
(call: unknown[]) => call[0] === "FN-C" && String(call[1]).includes("queued — concurrency limit reached"),
|
||||
);
|
||||
expect(concurrencyReasonCalls).toHaveLength(1);
|
||||
|
||||
const auditCalls = (store.recordRunAuditEvent as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||
(call: unknown[]) => (call[0] as { mutationType?: string } | undefined)?.mutationType === "scheduler:dispatch-queued-concurrency",
|
||||
);
|
||||
expect(auditCalls).toHaveLength(1);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.bindingGates).toEqual(["maxConcurrent"]);
|
||||
});
|
||||
|
||||
it("dedupes queued-concurrency logs when only non-binding semaphore counts change", async () => {
|
||||
@@ -1872,12 +1866,6 @@ describe("Scheduler", () => {
|
||||
(call: unknown[]) => call[0] === "FN-D" && String(call[1]).includes("queued — concurrency limit reached"),
|
||||
);
|
||||
expect(concurrencyReasonCalls).toHaveLength(1);
|
||||
|
||||
const auditCalls = (store.recordRunAuditEvent as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||
(call: unknown[]) => (call[0] as { mutationType?: string } | undefined)?.mutationType === "scheduler:dispatch-queued-concurrency",
|
||||
);
|
||||
expect(auditCalls).toHaveLength(1);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.bindingGates).toEqual(["maxWorktrees"]);
|
||||
});
|
||||
|
||||
it("dedupes queued-concurrency logs across used/limit churn on the same binding gate", async () => {
|
||||
@@ -1910,13 +1898,6 @@ describe("Scheduler", () => {
|
||||
);
|
||||
expect(concurrencyReasonCalls).toHaveLength(1);
|
||||
expect(String(concurrencyReasonCalls[0]?.[1])).toContain("semaphore used=1/2");
|
||||
|
||||
const auditCalls = (store.recordRunAuditEvent as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||
(call: unknown[]) => (call[0] as { mutationType?: string } | undefined)?.mutationType === "scheduler:dispatch-queued-concurrency",
|
||||
);
|
||||
expect(auditCalls).toHaveLength(1);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.bindingGates).toEqual(["semaphore"]);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.semaphore).toEqual({ used: 1, limit: 2, slack: 1 });
|
||||
});
|
||||
|
||||
it("suppresses re-log and re-audit when only binding holder identity changes", async () => {
|
||||
@@ -1950,13 +1931,6 @@ describe("Scheduler", () => {
|
||||
(call: unknown[]) => call[0] === "FN-D" && String(call[1]).includes("queued — concurrency limit reached"),
|
||||
);
|
||||
expect(concurrencyReasonCalls).toHaveLength(1);
|
||||
|
||||
const auditCalls = (store.recordRunAuditEvent as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||
(call: unknown[]) => (call[0] as { mutationType?: string } | undefined)?.mutationType === "scheduler:dispatch-queued-concurrency",
|
||||
);
|
||||
expect(auditCalls).toHaveLength(1);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.bindingGates).toEqual(["maxWorktrees"]);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.holders?.maxWorktrees).toEqual(["FN-A"]);
|
||||
});
|
||||
|
||||
it("re-logs and re-audits when binding gate changes", async () => {
|
||||
@@ -1995,13 +1969,6 @@ describe("Scheduler", () => {
|
||||
expect(concurrencyReasonCalls).toHaveLength(2);
|
||||
expect(String(concurrencyReasonCalls[0]?.[1])).toContain("gate=maxConcurrent");
|
||||
expect(String(concurrencyReasonCalls[1]?.[1])).toContain("gate=maxWorktrees");
|
||||
|
||||
const auditCalls = (store.recordRunAuditEvent as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||
(call: unknown[]) => (call[0] as { mutationType?: string } | undefined)?.mutationType === "scheduler:dispatch-queued-concurrency",
|
||||
);
|
||||
expect(auditCalls).toHaveLength(2);
|
||||
expect(auditCalls[0]?.[0]?.metadata?.bindingGates).toEqual(["maxConcurrent"]);
|
||||
expect(auditCalls[1]?.[0]?.metadata?.bindingGates).toEqual(["maxWorktrees"]);
|
||||
});
|
||||
|
||||
it("formats queued-concurrency memo keys from binding gates only", () => {
|
||||
|
||||
@@ -502,8 +502,6 @@ export class Scheduler {
|
||||
private wasPermanentAgentUnavailable = new Set<string>();
|
||||
/** Tracks dispatch-queued reason signatures to avoid per-tick log spam. */
|
||||
private wasDispatchQueuedReasonLogged = new Set<string>();
|
||||
/** Tracks the last stable concurrency-block signature emitted for a task. */
|
||||
private dispatchQueuedConcurrencyAuditMemo = new Map<string, string>();
|
||||
/** Tracks per-task candidacy fingerprints for task:updated auto-claim invalidation gating. */
|
||||
private lastAutoClaimFingerprint = new Map<string, string>();
|
||||
/** Tracks recent engine-sourced in-progress → todo requeues to prevent immediate re-dispatch races. */
|
||||
@@ -791,7 +789,6 @@ export class Scheduler {
|
||||
this.wasNodeBlocked.delete(task.id);
|
||||
this.wasPermanentAgentUnavailable.delete(task.id);
|
||||
this.clearDispatchQueuedReasonMemo(task.id);
|
||||
this.clearDispatchQueuedConcurrencyAuditMemo(task.id);
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
@@ -936,7 +933,6 @@ export class Scheduler {
|
||||
this.wasNodeDispatchValidationBlocked.clear();
|
||||
this.wasPermanentAgentUnavailable.clear();
|
||||
this.wasDispatchQueuedReasonLogged.clear();
|
||||
this.dispatchQueuedConcurrencyAuditMemo.clear();
|
||||
schedulerLog.log("Stopped");
|
||||
}
|
||||
|
||||
@@ -955,27 +951,11 @@ export class Scheduler {
|
||||
}
|
||||
|
||||
this.clearDispatchQueuedReasonMemo(taskId);
|
||||
if (!key.includes(":queued-concurrency:")) {
|
||||
this.clearDispatchQueuedConcurrencyAuditMemo(taskId);
|
||||
}
|
||||
this.wasDispatchQueuedReasonLogged.add(key);
|
||||
await this.store.logEntry(taskId, reason);
|
||||
return true;
|
||||
}
|
||||
|
||||
private shouldEmitDispatchQueuedConcurrencyAudit(taskId: string, signature: string): boolean {
|
||||
const lastSignature = this.dispatchQueuedConcurrencyAuditMemo.get(taskId);
|
||||
if (lastSignature === signature) {
|
||||
return false;
|
||||
}
|
||||
this.dispatchQueuedConcurrencyAuditMemo.set(taskId, signature);
|
||||
return true;
|
||||
}
|
||||
|
||||
private clearDispatchQueuedConcurrencyAuditMemo(taskId: string): void {
|
||||
this.dispatchQueuedConcurrencyAuditMemo.delete(taskId);
|
||||
}
|
||||
|
||||
private emitDependencyParityDiff(diff: SchedulingDependencyParityDiff): void {
|
||||
void this.store.recordRunAuditEvent?.({
|
||||
taskId: diff.taskId,
|
||||
@@ -992,33 +972,6 @@ export class Scheduler {
|
||||
});
|
||||
}
|
||||
|
||||
private async emitDispatchQueuedConcurrencyAudit(task: Task, diagnostic: ConcurrencyGateDiagnostic): Promise<void> {
|
||||
try {
|
||||
await this.store.recordRunAuditEvent?.({
|
||||
taskId: task.id,
|
||||
agentId: "scheduler",
|
||||
runId: generateSyntheticRunId("scheduler", task.id),
|
||||
domain: "database",
|
||||
mutationType: "scheduler:dispatch-queued-concurrency",
|
||||
target: task.id,
|
||||
metadata: {
|
||||
bindingGates: diagnostic.bindingGates,
|
||||
maxConcurrent: diagnostic.maxConcurrentGate,
|
||||
maxWorktrees: diagnostic.maxWorktreesGate,
|
||||
semaphore: diagnostic.semaphoreGate,
|
||||
holders: diagnostic.holders,
|
||||
available: diagnostic.available,
|
||||
// U6: additive per-column capacity gates (present only flag-ON).
|
||||
...(diagnostic.perColumnGates ? { perColumnGates: diagnostic.perColumnGates } : {}),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
schedulerLog.warn(
|
||||
`Task ${task.id} failed to emit dispatch queued concurrency audit: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async emitNodeUnreachableRecoveryAudit(
|
||||
task: Task,
|
||||
metadata: {
|
||||
@@ -1676,9 +1629,6 @@ export class Scheduler {
|
||||
reason,
|
||||
concurrencySignature,
|
||||
);
|
||||
if (this.shouldEmitDispatchQueuedConcurrencyAudit(task.id, concurrencySignature)) {
|
||||
await this.emitDispatchQueuedConcurrencyAudit(task, concurrencyGateDiagnostic);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2014,7 +1964,6 @@ export class Scheduler {
|
||||
this.wasNodeDispatchValidationBlocked.delete(task.id);
|
||||
this.wasPermanentAgentUnavailable.delete(task.id);
|
||||
this.clearDispatchQueuedReasonMemo(task.id);
|
||||
this.clearDispatchQueuedConcurrencyAuditMemo(task.id);
|
||||
await this.store.logEntry(task.id, `Node routing resolved: ${effectiveNode.nodeId ?? "local"} (source: ${effectiveNode.source})`);
|
||||
this.options.onSchedule?.(task);
|
||||
started++;
|
||||
|
||||
Reference in New Issue
Block a user