fix(desktop): forget in-memory paging state on a connection/mode re-home
wipeSessionListsForGatewaySwitch cleared the persisted transcript-tail cache but never the in-memory $transcriptTailBySessionId atom. Before this stack both an ambient local read and an ambient remote read of a recycled stored id landed under the bare-id key, so the newer backend simply overwrote the older. Owner-keyed entries coexist instead, and the unique-match lookup that gates "Show earlier" sees two candidates and fails closed for that session until eviction. Wipe the atom alongside the cache.
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
setSessionsLoading
|
||||
} from '@/store/session'
|
||||
import { $stalledSessionIds } from '@/store/session-states'
|
||||
import { $transcriptTailBySessionId, recordTranscriptTail, transcriptTailState } from '@/store/transcript-tail'
|
||||
|
||||
import {
|
||||
$gatewaySwitching,
|
||||
@@ -79,6 +80,28 @@ describe('wipeSessionListsForGatewaySwitch', () => {
|
||||
expect($freshDraftReady.get()).toBe(true)
|
||||
})
|
||||
|
||||
it("forgets the previous backend's in-memory paging state", () => {
|
||||
const page = {
|
||||
messages: Array.from({ length: 120 }, (_, index) => ({
|
||||
id: index,
|
||||
role: 'user' as const,
|
||||
content: '',
|
||||
timestamp: 1
|
||||
})),
|
||||
pagination: { limit: 120, offset: 0, order: 'latest' as const, returned: 120 }
|
||||
}
|
||||
|
||||
recordTranscriptTail('recycled-id', page, { connectionId: 'local', profile: 'default' })
|
||||
|
||||
wipeSessionListsForGatewaySwitch()
|
||||
|
||||
// A same-id session on the next backend must resolve its own tail alone.
|
||||
recordTranscriptTail('recycled-id', page, { connectionId: 'remote-1', profile: 'default' })
|
||||
expect(Object.keys($transcriptTailBySessionId.get())).toHaveLength(1)
|
||||
expect(transcriptTailState('recycled-id')?.possiblyTruncated).toBe(true)
|
||||
$transcriptTailBySessionId.set({})
|
||||
})
|
||||
|
||||
it('strands in-flight profile-list fetches so the old backend cannot repaint the rail (#85731)', () => {
|
||||
// The soft re-home moves /api/profiles routing to the NEW backend; a
|
||||
// response still in flight from the previous one must be invalidated
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
import { clearAllSessionControl } from '@/store/session-control'
|
||||
import { resetSessionPinMirror } from '@/store/session-pin-sync'
|
||||
import { clearAllSessionStates } from '@/store/session-states'
|
||||
import { clearAllTranscriptTails } from '@/store/transcript-tail'
|
||||
import { clearTranscriptTails } from '@/store/transcript-tail-cache'
|
||||
|
||||
// True while a connection switch is mid-flight — a Settings → Gateway apply
|
||||
@@ -227,8 +228,12 @@ export function wipeSessionListsForGatewaySwitch(): void {
|
||||
|
||||
// Cached transcript tails belong to the PREVIOUS backend's sessions; a
|
||||
// different backend can recycle stored ids, and painting another machine's
|
||||
// conversation under a same-named id is worse than a loader. Wipe them.
|
||||
// conversation under a same-named id is worse than a loader. Wipe both the
|
||||
// persisted cache and the in-memory paging entries — the latter are keyed by
|
||||
// owner, so a survivor from the old backend would sit beside the new one and
|
||||
// fail the unique-match lookup that shows "Show earlier".
|
||||
clearTranscriptTails()
|
||||
clearAllTranscriptTails()
|
||||
|
||||
// Narrowed: account/marketplace/onboarding caches are global, not gateway-
|
||||
// scoped, so a mode swap must not refetch them.
|
||||
|
||||
@@ -178,6 +178,13 @@ export function transcriptTailState(
|
||||
return matches.length === 1 ? matches[0][1] : undefined
|
||||
}
|
||||
|
||||
/** Forget every tail: the backend behind the window changed and a recycled
|
||||
* stored id must not carry the previous backend's paging state. */
|
||||
export function clearAllTranscriptTails(): void {
|
||||
transcriptTailOrder = []
|
||||
$transcriptTailBySessionId.set({})
|
||||
}
|
||||
|
||||
export function clearTranscriptTail(storedSessionId: string, profile?: TranscriptProfileScope): void {
|
||||
const current = $transcriptTailBySessionId.get()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user