feat(apiproxy): projection column on session.list — cold titles with zero log loads

SessionSummary grows an optional projections column (whole value per key,
same passthrough posture as the history-tail block): attached rows cut the
live registry watermark cache; cold rows view the persisted projection
cache's stored rows via the new registry viewCheckpoint face (version-
matching keys only, zero I/O) — the RFC's motivating scenario, every
session's title across a listing without loading one event log. The column
is fail-soft and absence-coded: no registry, no cache row, or a throwing
read serve the row without the column, never breaking the listing.
This commit is contained in:
imccyu
2026-07-28 01:38:15 +08:00
parent c330c1cd3e
commit 003b22a157
10 changed files with 187 additions and 5 deletions

View File

@@ -19,7 +19,7 @@ import type { Session, SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
// Empty type import: applies the package's cordis Context merge
// (`ctx.sessionPersistence`), which this service reads on the cold path.
import type {} from '@deepseek-ai/dsh-session-persistence'
import type { ProjectionCheckpoint, ProjectionSnapshot } from '@deepseek-ai/dsh-session-projection'
import type { ProjectionCheckpoint, ProjectionSnapshot, SessionProjectionMap } from '@deepseek-ai/dsh-session-projection'
import type { KvTable } from '@deepseek-ai/dsh-storage-domain'
import { projectionCacheDomainSpec } from './spec.ts'
import type { CheckpointRecord } from './spec.ts'
@@ -98,6 +98,20 @@ export class SessionProjectionCache extends Service {
return this.requireTable().get(id)?.rows ?? {}
}
/**
* The zero-I/O listing read: whole values viewed straight from the stored
* rows (version-matching keys only), as stale as the last durable
* checkpoint but never wrong. Synchronous — a listing over every stored
* session touches no log. Fresher paths (the history tail baseline,
* {@link coldSnapshot}) supersede these values whenever a session is
* actually opened.
* @param id - the session whose cached values are viewed.
* @returns whole values per key with a usable row; empty when none stored.
*/
cachedValues(id: SessionId): Partial<SessionProjectionMap> {
return this.ctx.sessionProjections.viewCheckpoint(this.checkpointOf(id))
}
/**
* Durably checkpoint one live session NOW (both mandatory points call
* this; tests and carriers may too). The registry cut is snapshotted at