From 8c67d49ca50aec1baae370057a736efb0cdcd540 Mon Sep 17 00:00:00 2001 From: pku-xht Date: Thu, 27 Aug 2026 11:02:06 +0800 Subject: [PATCH] fix(api): simplify projection reconciliation --- .../src/client/sessions/manager.ts | 31 +++---------------- .../src/client/sessions/projection-store.ts | 30 ++++++------------ 2 files changed, 14 insertions(+), 47 deletions(-) diff --git a/packages/api/session-controller/src/client/sessions/manager.ts b/packages/api/session-controller/src/client/sessions/manager.ts index 8cff3f47d8..30b50364ef 100644 --- a/packages/api/session-controller/src/client/sessions/manager.ts +++ b/packages/api/session-controller/src/client/sessions/manager.ts @@ -10,7 +10,6 @@ import type { SessionControlFrame, SessionQueuedItem, SessionError, - SessionProjectionHints, SessionSummary, SessionJob as JobView, } from '../../types.ts' @@ -489,7 +488,10 @@ export class SessionManager { session.handleBlank(s.blank) session.handleRunning(s.running) } - this.reconcileListProjectionHints(result.value.items, mutations) + for (const summary of this.summaries) { + const projections = summary.projections + if (projections !== undefined) this.projectionStore(summary.sessionId).prewarm(projections) + } } else { this.listState = 'error' this.listError = result.error @@ -705,31 +707,6 @@ export class SessionManager { this.notifier.markDirty() } - /** - * Apply pull-time hints before later list mutations without letting a stale - * in-flight response overwrite a newer session-added hint or recreate a - * Session removed while the request was pending. - */ - private reconcileListProjectionHints( - items: readonly SessionSummary[], - mutations: readonly SessionListMutation[], - ): void { - const hints = new Map() - for (const summary of items) { - if (summary.projections !== undefined) hints.set(summary.sessionId, summary.projections) - } - for (const mutation of mutations) { - if (mutation.kind === 'remove') { - hints.delete(mutation.sessionId) - } else if (mutation.kind === 'upsert' && mutation.summary.projections !== undefined) { - hints.set(mutation.summary.sessionId, mutation.summary.projections) - } - } - for (const [sessionId, hint] of hints) { - this.projectionStore(sessionId).prewarm(hint) - } - } - /** * Apply one Session-list addition forwarded through `ctx.remote.$on`. * @param summary - current Host summary for the added Session. diff --git a/packages/api/session-controller/src/client/sessions/projection-store.ts b/packages/api/session-controller/src/client/sessions/projection-store.ts index a198c05c80..bac640cf14 100644 --- a/packages/api/session-controller/src/client/sessions/projection-store.ts +++ b/packages/api/session-controller/src/client/sessions/projection-store.ts @@ -209,7 +209,7 @@ export class ProjectionValueStore { && row.revision > token.revision && row.seq > baseline.asOfSeq) this.completeBaselineInstalled = true - this.installCompleteBaseline(baseline, ++this.revision) + this.replaceRows(baseline, ++this.revision, 'authoritative') for (const [key, row] of retained) this.installRow(key, row) } @@ -231,7 +231,7 @@ export class ProjectionValueStore { const revision = ++this.revision this.completeBaselineInstalled = true this.latestControlBaseline = { revision, asOfSeq: baseline.asOfSeq } - this.installCompleteBaseline(baseline, revision) + this.replaceRows(baseline, revision, 'authoritative') } /** @@ -251,21 +251,7 @@ export class ProjectionValueStore { } return } - const values = hint.values as Record - const keys = new Set([...this.rows.keys(), ...Object.keys(values)]) - for (const key of keys) { - if (!Object.hasOwn(values, key)) { - this.rows.delete(key) - this.changed(key) - continue - } - this.installRow(key, { - value: values[key], - seq: hint.asOfSeq, - provenance: 'tentative', - revision, - }) - } + this.replaceRows(hint, revision, 'tentative') } private changed(key: string): void { @@ -274,8 +260,12 @@ export class ProjectionValueStore { this.anyNotifier.markDirty() } - /** Replace every row with one complete authoritative baseline. */ - private installCompleteBaseline(baseline: ProjectionsBaseline, revision: number): void { + /** Replace every row with one baseline at the supplied authority. */ + private replaceRows( + baseline: ProjectionsBaseline, + revision: number, + provenance: Row['provenance'], + ): void { const values = baseline.values as Record const keys = new Set([...this.rows.keys(), ...Object.keys(values)]) for (const key of keys) { @@ -287,7 +277,7 @@ export class ProjectionValueStore { this.installRow(key, { value: values[key], seq: baseline.asOfSeq, - provenance: 'authoritative', + provenance, revision, }) }