Browse Source

fix(api): simplify projection reconciliation

pku-xht 1 month ago
parent
commit
8c67d49ca5

+ 4 - 27
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<SessionId, SessionProjectionHints>()
-    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.

+ 10 - 20
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<string, unknown>
-    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<string, unknown>
     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,
       })
     }