fix(app): resolve target session lineage outside router transition (#34838)
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
createMemo,
|
||||
createEffect,
|
||||
createComputed,
|
||||
createResource,
|
||||
createSignal,
|
||||
on,
|
||||
onMount,
|
||||
type ParentProps,
|
||||
@@ -86,7 +86,7 @@ import { diffs as list } from "@/utils/diffs"
|
||||
import { Persist, persisted } from "@/utils/persist"
|
||||
import { extractPromptFromParts } from "@/utils/prompt"
|
||||
import { formatServerError, isSessionNotFoundError } from "@/utils/server-errors"
|
||||
import { legacySessionHref, requireServerKey, selectSessionLineage, sessionHref } from "@/utils/session-route"
|
||||
import { legacySessionHref, requireServerKey, sessionHref } from "@/utils/session-route"
|
||||
import { useUsageExceededDialogs } from "./session/usage-exceeded-dialogs"
|
||||
import { createSessionOwnership } from "./session/session-ownership"
|
||||
|
||||
@@ -224,17 +224,8 @@ function ResolvedTargetSessionRoute() {
|
||||
const params = useParams<{ serverKey: string; id: string }>()
|
||||
const settings = useSettings()
|
||||
const tabs = useTabs()
|
||||
const sync = useServerSync()
|
||||
const serverKey = createMemo(() => requireServerKey(params.serverKey))
|
||||
const cached = createMemo(() => sync().session.lineage.peek(params.id))
|
||||
const [resolved] = createResource(
|
||||
() => {
|
||||
if (cached()) return
|
||||
return { id: params.id, sync: sync() }
|
||||
},
|
||||
({ id, sync }) => sync.session.lineage.resolve(id),
|
||||
)
|
||||
const current = createMemo(() => selectSessionLineage(params.id, cached(), resolved()))
|
||||
const current = createSessionLineage(() => params.id)
|
||||
const directory = createMemo(() => current()?.session.directory)
|
||||
const targetDirectory = () => directory()!
|
||||
|
||||
@@ -265,6 +256,42 @@ function ResolvedTargetSessionRoute() {
|
||||
)
|
||||
}
|
||||
|
||||
// Reactive session lineage for the target session route, read from the sync store.
|
||||
// The route keys its consumer to the session ID, so resolution runs once per target.
|
||||
// Resolution is imperative rather than a resource on purpose: a resource created here
|
||||
// would be created inside the router's navigation transition, and suspending that
|
||||
// transition deadlocks the URL commit and double-mounts the session header portals
|
||||
// from the transition's shadow render. `lineage.resolve` fills the sync store, which
|
||||
// the returned accessor observes; resolve failures rethrow on read so the enclosing
|
||||
// SessionRouteErrorBoundary renders the scoped session error.
|
||||
function createSessionLineage(sessionID: () => string) {
|
||||
const sync = useServerSync()
|
||||
const cached = createMemo(() => sync().session.lineage.peek(sessionID()))
|
||||
const [failure, setFailure] = createSignal<unknown>()
|
||||
const [settled, setSettled] = createSignal(false)
|
||||
onMount(() => {
|
||||
if (cached()) {
|
||||
setSettled(true)
|
||||
return
|
||||
}
|
||||
sync()
|
||||
.session.lineage.resolve(sessionID())
|
||||
.then(() => setSettled(true))
|
||||
.catch((error) => setFailure(() => error))
|
||||
})
|
||||
return createMemo(() => {
|
||||
const error = failure()
|
||||
if (error) throw error
|
||||
const lineage = cached()
|
||||
// The viewed session is pinned and pinned lineages are exempt from cache pruning,
|
||||
// so a lineage missing after settlement means the session (or an ancestor) was
|
||||
// deleted, possibly by another client. Match the resolve error so the boundary
|
||||
// shows the session not found fallback.
|
||||
if (!lineage && settled()) throw new Error(`Session not found: ${sessionID()}`)
|
||||
return lineage
|
||||
})
|
||||
}
|
||||
|
||||
function TargetSessionPage() {
|
||||
const sdk = useSDK()
|
||||
const serverSDK = useServerSDK()
|
||||
|
||||
Reference in New Issue
Block a user