refactor(app): centralize perf diagnostics and activity coalescing
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
export type {
|
||||
ActivityFlushHandle,
|
||||
AgentLastActivityCoalescer,
|
||||
AgentLastActivityCommitter,
|
||||
AgentLastActivityUpdates,
|
||||
} from "./types";
|
||||
|
||||
export { scheduleAgentLastActivityFlush } from "./last-activity-scheduler";
|
||||
export { createAgentLastActivityCoalescer } from "./last-activity-coalescer";
|
||||
@@ -0,0 +1,67 @@
|
||||
import { scheduleAgentLastActivityFlush } from "./last-activity-scheduler";
|
||||
import type {
|
||||
ActivityFlushHandle,
|
||||
AgentLastActivityCoalescer,
|
||||
AgentLastActivityCommitter,
|
||||
} from "./types";
|
||||
|
||||
export function createAgentLastActivityCoalescer(): AgentLastActivityCoalescer {
|
||||
let pending = new Map<string, Date>();
|
||||
let scheduledFlush: ActivityFlushHandle | null = null;
|
||||
let committer: AgentLastActivityCommitter | null = null;
|
||||
|
||||
const cancelScheduledFlush = () => {
|
||||
if (!scheduledFlush) {
|
||||
return;
|
||||
}
|
||||
scheduledFlush.cancel();
|
||||
scheduledFlush = null;
|
||||
};
|
||||
|
||||
const flushNow = () => {
|
||||
cancelScheduledFlush();
|
||||
if (pending.size === 0) {
|
||||
return;
|
||||
}
|
||||
const updates = pending;
|
||||
pending = new Map();
|
||||
committer?.(updates);
|
||||
};
|
||||
|
||||
const scheduleFlush = () => {
|
||||
if (scheduledFlush) {
|
||||
return;
|
||||
}
|
||||
scheduledFlush = scheduleAgentLastActivityFlush(() => {
|
||||
scheduledFlush = null;
|
||||
flushNow();
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
setCommitter(nextCommitter) {
|
||||
committer = nextCommitter;
|
||||
},
|
||||
|
||||
enqueue(agentId, timestamp) {
|
||||
const current = pending.get(agentId);
|
||||
if (current && current.getTime() >= timestamp.getTime()) {
|
||||
return;
|
||||
}
|
||||
pending.set(agentId, timestamp);
|
||||
scheduleFlush();
|
||||
},
|
||||
|
||||
flushNow,
|
||||
|
||||
deletePending(agentId) {
|
||||
pending.delete(agentId);
|
||||
},
|
||||
|
||||
dispose() {
|
||||
cancelScheduledFlush();
|
||||
pending.clear();
|
||||
committer = null;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { ActivityFlushHandle } from "./types";
|
||||
|
||||
const DEFAULT_ACTIVITY_FLUSH_INTERVAL_MS = 16;
|
||||
|
||||
export function scheduleAgentLastActivityFlush(
|
||||
callback: () => void,
|
||||
fallbackIntervalMs = DEFAULT_ACTIVITY_FLUSH_INTERVAL_MS
|
||||
): ActivityFlushHandle {
|
||||
if (typeof requestAnimationFrame === "function") {
|
||||
const handle = requestAnimationFrame(callback);
|
||||
return {
|
||||
cancel: () => {
|
||||
if (typeof cancelAnimationFrame === "function") {
|
||||
cancelAnimationFrame(handle);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const handle = setTimeout(callback, fallbackIntervalMs);
|
||||
return {
|
||||
cancel: () => {
|
||||
clearTimeout(handle);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
export type AgentLastActivityUpdates = Map<string, Date>;
|
||||
|
||||
export type AgentLastActivityCommitter = (
|
||||
updates: AgentLastActivityUpdates
|
||||
) => void;
|
||||
|
||||
export interface ActivityFlushHandle {
|
||||
cancel: () => void;
|
||||
}
|
||||
|
||||
export interface AgentLastActivityCoalescer {
|
||||
setCommitter: (committer: AgentLastActivityCommitter | null) => void;
|
||||
enqueue: (agentId: string, timestamp: Date) => void;
|
||||
flushNow: () => void;
|
||||
deletePending: (agentId: string) => void;
|
||||
dispose: () => void;
|
||||
}
|
||||
Reference in New Issue
Block a user