fix(web): narrow request lifecycle fences
This commit is contained in:
@@ -136,8 +136,7 @@ describe('runtime client apply', () => {
|
||||
bench.sinks?.onDisconnected?.()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
|
||||
// A second failed generation does not produce another deduplicated
|
||||
// `reconnecting` state transition, but its own disconnect callback still
|
||||
// Every failed generation invokes its own disconnect callback, which
|
||||
// clears telemetry received before that generation's handshake failed.
|
||||
bench.sinks?.onMuxEnvelope?.({
|
||||
rpcId: 'request-2' as never,
|
||||
|
||||
@@ -169,6 +169,26 @@ describe('instances', () => {
|
||||
},
|
||||
})
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'resumed-subscription' as never,
|
||||
payload: { type: 'session/subscribed', sessionId: S1, lastSeq: 0 },
|
||||
})
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'resumed-request' as never,
|
||||
payload: {
|
||||
type: 'session/model-request',
|
||||
sessionId: S1,
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'resumed',
|
||||
contextWindow: 256_000,
|
||||
},
|
||||
})
|
||||
expect(session.getSnapshot().modelRequest).toMatchObject({
|
||||
model: 'resumed',
|
||||
contextWindow: 256_000,
|
||||
})
|
||||
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'request-before-lazy-removal' as never,
|
||||
|
||||
@@ -833,8 +833,9 @@ describe('resync', () => {
|
||||
expect(session.getSnapshot()).toMatchObject({
|
||||
openState: 'error',
|
||||
openError: {
|
||||
code: 'internal',
|
||||
message: 'connection lost while loading session history',
|
||||
code: 'cancelled',
|
||||
message: 'session history request cancelled after connection loss',
|
||||
details: {},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -843,12 +844,34 @@ describe('resync', () => {
|
||||
expect(session.getSnapshot()).toMatchObject({
|
||||
openState: 'error',
|
||||
openError: {
|
||||
code: 'internal',
|
||||
message: 'connection lost while loading session history',
|
||||
code: 'cancelled',
|
||||
message: 'session history request cancelled after connection loss',
|
||||
details: {},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('settles an in-flight older-page load when its connection generation dies', async () => {
|
||||
const { api, session } = makeSession()
|
||||
api.onHistory = () => histResponse(plainTurn(6, 1, '新问', '新答'), true)
|
||||
await session.open()
|
||||
const stale = deferred<Awaited<ReturnType<FakeApiClient['onHistory']>>>()
|
||||
api.onHistory = () => stale.promise
|
||||
const paging = session.loadOlder()
|
||||
expect(session.getSnapshot().loadingOlder).toBe(true)
|
||||
|
||||
session.handleReconnecting()
|
||||
expect(session.getSnapshot().loadingOlder).toBe(false)
|
||||
|
||||
stale.resolve(ok({
|
||||
events: entries(plainTurn(0, 0, '旧问', '旧答')) as never[],
|
||||
hasMore: false,
|
||||
}))
|
||||
await paging
|
||||
expect(session.getSnapshot().loadingOlder).toBe(false)
|
||||
expect(session.getSnapshot().nodes.map(node => node.seq)).toEqual([7, 9])
|
||||
})
|
||||
|
||||
it('clears request telemetry on reconnect and drops a stale in-flight history response', async () => {
|
||||
const { api, session } = makeSession()
|
||||
const stale = deferred<Awaited<ReturnType<FakeApiClient['onHistory']>>>()
|
||||
|
||||
Reference in New Issue
Block a user