diff options
| author | Adam Malczewski <[email protected]> | 2026-06-07 00:02:32 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-07 00:02:32 +0900 |
| commit | 5d9ae1849337b64af1b0d47c23b8c4950a55f792 (patch) | |
| tree | dd5fccaff7535bf1216457a986b8f95bd14fd61e /src/features/conversation-cache/types.ts | |
| parent | fac44794432928d0341728642fd70eef87837da4 (diff) | |
| download | dispatch-web-5d9ae1849337b64af1b0d47c23b8c4950a55f792.tar.gz dispatch-web-5d9ae1849337b64af1b0d47c23b8c4950a55f792.zip | |
Slice 2 wave 1: transcript reducer, wire conformance, ws chat, cache core
- core/chunks: the one pure transcript reducer (foldEvent live deltas +
applyHistory seq-keyed reconcile + selectChunks/selectMessages); 27 tests
- core/wire: FE-side contract-conformance exhaustiveness guards + drift smoke
tests over wire/transport-contract unions (ยง2.9 drift signal); 10 tests
- adapters/ws: additively multiplex chat.send/chat.delta/chat.error on the
existing surface socket (onChat + widened send); surface API unchanged
- features/conversation-cache: pure reconcileCache/nextSinceSeq/selectEvictions
+ ConversationChunkStore port + injected createConversationCache; 26 tests
Verified green: svelte-check 0/0, vitest 169, biome clean, build ok.
Diffstat (limited to 'src/features/conversation-cache/types.ts')
| -rw-r--r-- | src/features/conversation-cache/types.ts | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/features/conversation-cache/types.ts b/src/features/conversation-cache/types.ts new file mode 100644 index 0000000..2a349cc --- /dev/null +++ b/src/features/conversation-cache/types.ts @@ -0,0 +1,42 @@ +import type { StoredChunk } from "@dispatch/wire"; + +/** Metadata entry for a cached conversation, used by eviction logic. */ +export interface ConversationCacheIndexEntry { + readonly conversationId: string; + readonly chunkCount: number; + readonly maxSeq: number; + readonly lastAccess?: number; +} + +/** + * Storage port for conversation chunk persistence. + * + * The IndexedDB implementation lives in `src/adapters/idb/` (separate unit); + * this interface is the contract the cache logic depends on. + * + * All methods MUST be idempotent on `seq`: re-appending an existing seq is a no-op. + */ +export interface ConversationChunkStore { + /** Load all cached chunks for a conversation, seq-ordered. Returns [] if absent. */ + load(conversationId: string): Promise<readonly StoredChunk[]>; + + /** + * Append committed chunks to a conversation's cache. + * MUST be idempotent on `seq`: re-appending an existing seq is a no-op. + */ + append(conversationId: string, chunks: readonly StoredChunk[]): Promise<void>; + + /** Delete all cached data for a conversation. */ + delete(conversationId: string): Promise<void>; + + /** Return metadata for all cached conversations (for eviction). */ + index(): Promise<readonly ConversationCacheIndexEntry[]>; +} + +/** Result of reconciling cached chunks with incoming authoritative chunks. */ +export interface ReconcileResult { + /** The merged, deduplicated, seq-ordered chunk list. */ + readonly merged: readonly StoredChunk[]; + /** The subset of incoming chunks that need to be appended (not already cached). */ + readonly toAppend: readonly StoredChunk[]; +} |
