perf(dashboard): kill startup SSE storm and slim hot-path task scans
- TaskStore.watch() now initializes lastPollTime so the first
checkForChanges() poll filters by "modified since now" instead of
doing an unfiltered SELECT * and emitting a task:updated event for
every cached task. On a 1200-task board this dropped ~60 MB of SSE
traffic and a 1199-call setState storm one second after dashboard
startup.
- listTasks() gains a column option so callers can filter in SQL.
- dashboard CLI auto-merge sweeps (startup + 2 unpause handlers + the
15s periodic retry) now use listTasks({ column: "in-review" })
instead of pulling the full table on every cycle.
- self-healing archiveStaleDoneTasks() uses slim listTasks — it only
needs id/column/columnMovedAt to decide staleness.
- Document the listTasks() perf contract and the watch() polling
invariant in AGENTS.md and project memory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -876,7 +876,7 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
|
||||
|
||||
// ── Startup sweep: enqueue any tasks already in "in-review" ───────
|
||||
if (settings.autoMerge) {
|
||||
const existing = await store.listTasks();
|
||||
const existing = await store.listTasks({ column: "in-review" });
|
||||
const inReview = existing.filter((t) => canAutoMergeTask(t as any));
|
||||
if (inReview.length > 0) {
|
||||
console.log(
|
||||
@@ -911,7 +911,7 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
|
||||
|
||||
if (s.autoMerge) {
|
||||
try {
|
||||
const tasks = await store.listTasks();
|
||||
const tasks = await store.listTasks({ column: "in-review" });
|
||||
for (const t of tasks) {
|
||||
if (canAutoMergeTask(t as any)) {
|
||||
enqueueMerge(t.id);
|
||||
@@ -935,7 +935,7 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
|
||||
|
||||
if (s.autoMerge) {
|
||||
try {
|
||||
const tasks = await store.listTasks();
|
||||
const tasks = await store.listTasks({ column: "in-review" });
|
||||
for (const t of tasks) {
|
||||
if (canAutoMergeTask(t as any)) {
|
||||
enqueueMerge(t.id);
|
||||
@@ -999,7 +999,7 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
|
||||
// Refresh the cached limit so the semaphore picks up live changes
|
||||
cachedMaxConcurrent = s.maxConcurrent;
|
||||
if (!s.globalPause && !s.enginePaused && s.autoMerge) {
|
||||
const tasks = await store.listTasks();
|
||||
const tasks = await store.listTasks({ column: "in-review" });
|
||||
for (const t of tasks) {
|
||||
if (canAutoMergeTask(t as any)) {
|
||||
enqueueMerge(t.id);
|
||||
|
||||
Reference in New Issue
Block a user