refactor(desktop): one canonical write shape for connection_id row stamping
Reconcile #94901's API-layer row stamping with #94656's durable-owner persistence: extract lib/session-owner-stamp.ts as THE canonical stamp-untagged-rows write path (never clobbers an explicit owner, never stamps `local`) and re-express api/sessions' stampActiveConnectionOwner through it. #94656's writers (optimistic row from the captured owner route, mergeSessionPage carry, cache patch) are exact-owner writers and stay as-is; the helper's contract documents why it must not overwrite them. Credit: row-stamping concept from PR #94901 (joe-rodgers) and PR #95007 (weismanfamily); persistence shape from PR #94656 (Zeus-Deus). Co-authored-by: joe-rodgers <25499388+joe-rodgers@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { isMissingRestEndpoint } from '@/lib/gateway-rpc'
|
||||
import { stampRowsWithOwningConnection } from '@/lib/session-owner-stamp'
|
||||
import { recordTranscriptTail } from '@/store/transcript-tail'
|
||||
import type {
|
||||
PaginatedSessions,
|
||||
@@ -37,16 +38,11 @@ function sessionScopeQuery(scope?: ProfileScope): string {
|
||||
* correctly know nothing about this Desktop-local registry id. Preserve an
|
||||
* explicit owner from a multi-source response; otherwise stamp the active
|
||||
* non-local source so a later resume cannot fall back to a same-named local
|
||||
* profile.
|
||||
* profile. Delegates to the canonical row-stamp helper so this stays the ONE
|
||||
* write shape for connection_id on backend-returned rows.
|
||||
*/
|
||||
function stampActiveConnectionOwner(sessions: SessionInfo[]): SessionInfo[] {
|
||||
const connectionId = getApiRequestConnection()?.trim()
|
||||
|
||||
if (!connectionId || connectionId === 'local') {
|
||||
return sessions
|
||||
}
|
||||
|
||||
return sessions.map(session => (session.connection_id ? session : { ...session, connection_id: connectionId }))
|
||||
return stampRowsWithOwningConnection(sessions, getApiRequestConnection())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { SessionInfo } from '@/types/hermes'
|
||||
|
||||
/**
|
||||
* THE canonical write path for tagging backend-returned session rows with the
|
||||
* registry connection that owns them (the read counterpart is
|
||||
* `sessionOwnerRouteFromRow` in store/session-request-router).
|
||||
*
|
||||
* Every other `connection_id` writer works from an EXACT captured owner route
|
||||
* (the optimistic row in upsertOptimisticSession, the cache patch in
|
||||
* use-session-actions/utils, the mergeSessionPage carry) — those are
|
||||
* authoritative and this helper must never clobber them, so a row that
|
||||
* already names an owner is returned untouched. Only untagged rows served by
|
||||
* an active NON-local source get stamped: the gateway's HTTP APIs correctly
|
||||
* know nothing about Desktop-local registry ids, and an untagged remote row
|
||||
* would let a later resume fall back to a same-named local profile
|
||||
* ("session not found" on turn two). `local` is never stamped — a bare local
|
||||
* row already routes correctly and a `local` tag would only pin it against
|
||||
* the fail-closed owner resolution for no benefit.
|
||||
*/
|
||||
export function stampRowsWithOwningConnection(sessions: SessionInfo[], connectionId: null | string | undefined): SessionInfo[] {
|
||||
const owner = String(connectionId ?? '').trim()
|
||||
|
||||
if (!owner || owner === 'local') {
|
||||
return sessions
|
||||
}
|
||||
|
||||
return sessions.map(session => (session.connection_id?.trim() ? session : { ...session, connection_id: owner }))
|
||||
}
|
||||
Reference in New Issue
Block a user