返回源码地图

packages/session/session-persistence/src/handle.ts

main snapshot · da00f7f5358f · 正文引用章节 16;完整原文可核对,不声称全文件人工逐行审计

完整原文供逐行核对;页面收录不代表每行都经过人工语义审核。MIT 许可见 许可证。

1/**
2 * The per-session storage handle: one open channel onto a stored session's
3 * append-only event log, returned by `SessionPersistence.create`/`open`.
4 * @module @deepseek-ai/dsh-session-persistence/handle
5 */
6
7import type { SessionEvent, SessionHeader, SessionId, SessionLogOffset, SessionSeedEventState } from '@deepseek-ai/dsh-session'
8
9/**
10 * Log access granted by an open. `write` is read-write: the session's single
11 * mutator, which also reads its own log. `read` only observes — it never
12 * takes ownership and works while another handle or process holds `write`.
13 */
14export type SessionAccess = 'read' | 'write'
15
16/** Options for {@link SessionHandle.read}. */
17export interface SessionHandleReadOptions {
18 /** Optional cancellation for backend read work. */
19 readonly signal?: AbortSignal
20}
21
22/** One persistence event slice returned by {@link SessionHandle.read}. */
23export interface SessionHandleReadResult {
24 /**
25 * Whether event values are exclusively owned or shared only after deep
26 * freezing. Slicing preserves the producer's state even when no events remain.
27 */
28 readonly eventState: SessionSeedEventState
29 /** Event values in a caller-owned outer array. */
30 readonly events: readonly SessionEvent[]
31}
32
33/** Options for {@link SessionHandle.append}. */
34export interface SessionHandleAppendOptions {
35 /** Optional cancellation observed before the write starts. */
36 readonly signal?: AbortSignal
37}
38
39/** Options for {@link SessionHandle.flush}. */
40export interface SessionHandleFlushOptions {
41 /** Optional cancellation observed before the barrier starts. */
42 readonly signal?: AbortSignal
43}
44
45/**
46 * One open channel onto a stored session. A handle is single-owner state, not
47 * a shared service: `read` never backtracks below what this handle already
48 * observed, a `write` handle reads its own successful appends, and `close()`
49 * is the one teardown (idempotent, uncancellable; `Symbol.asyncDispose`
50 * delegates to it). Every operation on a closed handle rejects with
51 * `SessionHandleClosedError`.
52 *
53 * Freshness across handles: once an `append` or `flush` resolves on a write
54 * handle, every read STARTED afterwards on the same backend instance — on any
55 * handle, or through `stat`/`list` — observes at least that prefix.
56 * Reads concurrent with a mutation carry no ordering promise beyond the valid
57 * contiguous prefix.
58 */
59export interface SessionHandle extends AsyncDisposable {
60 /** The stored session this handle addresses. */
61 readonly id: SessionId
62 /** The immutable stored header, fixed at `create`/`open`. */
63 readonly header: SessionHeader
64 /**
65 * Exact fork-inherited prefix length stored with the log; `0` when
66 * `header.isSeeded` is false. Storage metadata paired with the header for
67 * every body read, never part of the replayable event log.
68 */
69 readonly inheritedEventCount: SessionLogOffset
70 /** Whether this handle may mutate the log. */
71 readonly access: SessionAccess
72
73 /**
74 * Read a slice of the valid contiguous logical log. The slice is a legal log
75 * prefix segment: a torn physical tail is never returned, and repeated reads
76 * on this handle never observe an older state than a prior read.
77 * @param offset - first logical event seq to include; defaults to `0`.
78 * @param length - maximum number of events to return; defaults to the rest
79 * of the log. An offset at or past the end returns an empty list.
80 * @param options - optional cancellation.
81 * @returns the caller-owned outer slice plus the ownership state of its event values.
82 */
83 read(offset?: number, length?: number, options?: SessionHandleReadOptions): Promise<SessionHandleReadResult>
84
85 /**
86 * Append a contiguous batch continuing the current logical end. The first
87 * event's `seq` MUST equal the stored next-seq; committed events are never
88 * rewritten. Persistence is best-effort: on resolution the batch is
89 * accepted, ordered, and visible to reads on this backend instance, but
90 * only a resolved {@link flush} promises it survives a crash — a backend
91 * may buffer or batch physical writes behind append. Rejects with
92 * `SessionReadOnlyError` on a read handle and `SessionOwnershipLostError`
93 * when write ownership is gone.
94 * @param events - the contiguous batch, in seq order.
95 * @param options - optional cancellation observed before the write starts.
96 */
97 append(events: readonly SessionEvent[], options?: SessionHandleAppendOptions): Promise<void>
98
99 /**
100 * The durability barrier — the one operation that promises storage: on
101 * resolution every acknowledged append is durable and the session is
102 * materialized for other processes; an empty created session becomes
103 * durably listable here. Callers that must survive a crash flush; a backend
104 * whose `append` already persists on resolution treats this as
105 * materialize-if-needed. Rejects with `SessionReadOnlyError` on a read
106 * handle.
107 * @param options - optional cancellation observed before the barrier starts.
108 */
109 flush(options?: SessionHandleFlushOptions): Promise<void>
110
111 /**
112 * Release the handle: a read handle frees local resources; a write handle
113 * completes pending durability and releases write ownership. Idempotent,
114 * asynchronous, and deliberately not cancellable.
115 */
116 close(): Promise<void>
117}