refactor(agent-loop): simplify observable state machine

This commit is contained in:
_Kerman
2026-07-24 21:18:48 +08:00
parent fb0ef82aa6
commit b73eb7663c
131 changed files with 2011 additions and 4292 deletions
@@ -154,6 +154,8 @@ export class PersistenceCoordinator<TornMarker = unknown> {
private states = new Map<SessionId, SessionState>()
/** Lifecycle and write-behind state keyed by the exact live Session. */
private live = new Map<Session, LiveSessionState>()
/** Exact disposed lifecycles whose eager tail is still draining. */
private retirements = new Map<SessionId, Promise<void>>()
/** Cold loads currently reserving an id across backend reads and repair writes. */
private coldLoads = new Set<SessionId>()
/**
@@ -250,6 +252,7 @@ export class PersistenceCoordinator<TornMarker = unknown> {
* @returns the header plus the event log, ending on a balanced `turn/end`.
*/
async load(id: SessionId): Promise<{ meta: SessionHeader; events: SessionEvent[] }> {
await this.retirements.get(id)
const selected = await this.serialize(id, async () => {
const live = this.ctx.sessions.get(id)
if (live !== undefined) return { live }
@@ -270,7 +273,8 @@ export class PersistenceCoordinator<TornMarker = unknown> {
* @returns stored header and events before any synthetic recovery closers.
*/
inspect(id: SessionId): Promise<{ meta: SessionHeader; events: SessionEvent[] }> {
return this.serialize(id, () => this.inspectCore(id))
return Promise.resolve(this.retirements.get(id))
.then(() => this.serialize(id, () => this.inspectCore(id)))
}
private async inspectCore(id: SessionId): Promise<{ meta: SessionHeader; events: SessionEvent[] }> {
@@ -432,7 +436,13 @@ export class PersistenceCoordinator<TornMarker = unknown> {
/** Start and observe one disposed session's final drain. */
private retire(session: Session): void {
if (!this.live.has(session)) return
void this.retireCore(session).catch((error: unknown) => {
const retirement = this.retireCore(session)
this.retirements.set(session.id, retirement)
const forget = (): void => {
if (this.retirements.get(session.id) === retirement) this.retirements.delete(session.id)
}
void retirement.then(forget, forget)
void retirement.catch((error: unknown) => {
this.ctx.logger.warn(`${this.backend.name}: session "${session.id}" retirement failed: ${String(error)}`)
})
}