@x1a0f3n9/dsh-session-persistence 0.1.2-alpha.6 → 0.1.5-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +45 -28
- package/README.zh.md +48 -31
- package/lib/index.js +184 -1519
- package/lib/types/errors.d.ts +98 -2
- package/lib/types/handle.d.ts +108 -0
- package/lib/types/index.d.ts +155 -194
- package/lib/types/storage-contract.d.ts +62 -0
- package/package.json +9 -9
- package/lib/types/coordinator.d.ts +0 -378
- package/lib/types/preparations.d.ts +0 -129
- package/lib/types/write-behind.d.ts +0 -62
package/lib/types/errors.d.ts
CHANGED
|
@@ -1,9 +1,105 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Stable failures exposed by the session-persistence service and its handles,
|
|
3
|
+
* including the format refusals shared by every backend: a stored log this
|
|
4
|
+
* build cannot faithfully interpret is refused, never misread, and the
|
|
5
|
+
* refusal points at the raw artifact when the backend keeps one per session.
|
|
6
|
+
* @module @x1a0f3n9/dsh-session-persistence/errors
|
|
7
|
+
*/
|
|
2
8
|
import type { SessionId } from '@x1a0f3n9/dsh-session';
|
|
3
|
-
/** The requested Session identity has no
|
|
9
|
+
/** The requested Session identity has no durable log visible to this caller. */
|
|
4
10
|
export declare class SessionPersistenceNotFoundError extends Error {
|
|
5
11
|
readonly sessionId: SessionId;
|
|
6
12
|
/** @param sessionId - absent durable Session identity. */
|
|
7
13
|
constructor(sessionId: SessionId);
|
|
8
14
|
}
|
|
15
|
+
/** `create` targeted a Session identity that already exists in this backend. */
|
|
16
|
+
export declare class SessionAlreadyExistsError extends Error {
|
|
17
|
+
readonly sessionId: SessionId;
|
|
18
|
+
/** @param sessionId - the occupied durable Session identity. */
|
|
19
|
+
constructor(sessionId: SessionId);
|
|
20
|
+
}
|
|
21
|
+
/** A write open found the session already bound to an active write handle. */
|
|
22
|
+
export declare class SessionAlreadyOwnedError extends Error {
|
|
23
|
+
readonly sessionId: SessionId;
|
|
24
|
+
/** @param sessionId - the session whose write ownership is taken. */
|
|
25
|
+
constructor(sessionId: SessionId);
|
|
26
|
+
}
|
|
27
|
+
/** A mutation (`append`/`flush`) was called on a read handle. */
|
|
28
|
+
export declare class SessionReadOnlyError extends Error {
|
|
29
|
+
readonly sessionId: SessionId;
|
|
30
|
+
/**
|
|
31
|
+
* @param sessionId - the session the read handle observes.
|
|
32
|
+
* @param operation - the refused mutating operation name.
|
|
33
|
+
*/
|
|
34
|
+
constructor(sessionId: SessionId, operation: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A write handle's ownership is permanently gone: its lease expired, a renewal
|
|
38
|
+
* failed, or the durable ownership record no longer names this handle. The
|
|
39
|
+
* handle never re-acquires ownership — close it and reopen for write.
|
|
40
|
+
*
|
|
41
|
+
* Declared for the cross-process lease layer; the shipped in-process backends
|
|
42
|
+
* never throw it yet.
|
|
43
|
+
*/
|
|
44
|
+
export declare class SessionOwnershipLostError extends Error {
|
|
45
|
+
readonly sessionId: SessionId;
|
|
46
|
+
/** @param sessionId - the session whose write ownership this handle lost. */
|
|
47
|
+
constructor(sessionId: SessionId);
|
|
48
|
+
}
|
|
49
|
+
/** An operation was called on a handle after `close()` was called. */
|
|
50
|
+
export declare class SessionHandleClosedError extends Error {
|
|
51
|
+
readonly sessionId: SessionId;
|
|
52
|
+
/**
|
|
53
|
+
* @param sessionId - the session the closed handle addressed.
|
|
54
|
+
* @param operation - the refused operation name.
|
|
55
|
+
*/
|
|
56
|
+
constructor(sessionId: SessionId, operation: string);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A backend-resolved, per-session local artifact location. Carried only by
|
|
60
|
+
* refusal diagnostics ({@link SessionFormatUnsupportedError}) so a user can
|
|
61
|
+
* find the raw log a build refused to interpret; it is not a consumer-facing
|
|
62
|
+
* query — log access goes through a session handle's `read`.
|
|
63
|
+
*/
|
|
64
|
+
export interface SessionLocation {
|
|
65
|
+
/** Backend-specific artifact kind, for example `jsonl`. */
|
|
66
|
+
readonly kind: string;
|
|
67
|
+
/** Absolute path to this session's backend-owned artifact. */
|
|
68
|
+
readonly path: string;
|
|
69
|
+
}
|
|
70
|
+
/** Durable session contents failed validation after a successful backend read. */
|
|
71
|
+
export declare class SessionPersistenceCorruptionError extends Error {
|
|
72
|
+
/**
|
|
73
|
+
* @param message - stable corruption context.
|
|
74
|
+
* @param options - original validation failure.
|
|
75
|
+
*/
|
|
76
|
+
constructor(message: string, options: ErrorOptions);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The stored log is intact but this runtime cannot faithfully interpret it:
|
|
80
|
+
* the header carries an unsupported format version, or an event's type is
|
|
81
|
+
* unknown to this build. Distinct from {@link SessionPersistenceCorruptionError}
|
|
82
|
+
* — nothing is damaged; the raw log remains readable at {@link location} when
|
|
83
|
+
* the backend keeps one artifact per session.
|
|
84
|
+
*/
|
|
85
|
+
export declare class SessionFormatUnsupportedError extends Error {
|
|
86
|
+
readonly location?: SessionLocation | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* @param message - stable reason the log cannot be interpreted, already
|
|
89
|
+
* including the raw-log path when one exists.
|
|
90
|
+
* @param location - the backend's artifact location, when one exists.
|
|
91
|
+
*/
|
|
92
|
+
constructor(message: string, location?: SessionLocation | undefined);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Direction-aware refusal text for a stored session whose format version this
|
|
96
|
+
* build does not read. Shared by load-time checks and by backends that must
|
|
97
|
+
* refuse BEFORE decoding version-dependent structure (a future format may not
|
|
98
|
+
* satisfy this build's structural checks at all, and the user must see
|
|
99
|
+
* "upgrade the harness", never "corrupt").
|
|
100
|
+
* @param id - the stored session id, for message context.
|
|
101
|
+
* @param version - the stored format version.
|
|
102
|
+
* @returns the stable refusal text, without a raw-log path suffix.
|
|
103
|
+
*/
|
|
104
|
+
export declare function sessionFormatVersionRefusal(id: string, version: number): string;
|
|
9
105
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
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 @x1a0f3n9/dsh-session-persistence/handle
|
|
5
|
+
*/
|
|
6
|
+
import type { SessionEvent, SessionHeader, SessionId, SessionLogOffset, SessionSeedEventState } from '@x1a0f3n9/dsh-session';
|
|
7
|
+
/**
|
|
8
|
+
* Log access granted by an open. `write` is read-write: the session's single
|
|
9
|
+
* mutator, which also reads its own log. `read` only observes — it never
|
|
10
|
+
* takes ownership and works while another handle or process holds `write`.
|
|
11
|
+
*/
|
|
12
|
+
export type SessionAccess = 'read' | 'write';
|
|
13
|
+
/** Options for {@link SessionHandle.read}. */
|
|
14
|
+
export interface SessionHandleReadOptions {
|
|
15
|
+
/** Optional cancellation for backend read work. */
|
|
16
|
+
readonly signal?: AbortSignal;
|
|
17
|
+
}
|
|
18
|
+
/** One persistence event slice returned by {@link SessionHandle.read}. */
|
|
19
|
+
export interface SessionHandleReadResult {
|
|
20
|
+
/**
|
|
21
|
+
* Whether event values are exclusively owned or shared only after deep
|
|
22
|
+
* freezing. Slicing preserves the producer's state even when no events remain.
|
|
23
|
+
*/
|
|
24
|
+
readonly eventState: SessionSeedEventState;
|
|
25
|
+
/** Event values in a caller-owned outer array. */
|
|
26
|
+
readonly events: readonly SessionEvent[];
|
|
27
|
+
}
|
|
28
|
+
/** Options for {@link SessionHandle.append}. */
|
|
29
|
+
export interface SessionHandleAppendOptions {
|
|
30
|
+
/** Optional cancellation observed before the write starts. */
|
|
31
|
+
readonly signal?: AbortSignal;
|
|
32
|
+
}
|
|
33
|
+
/** Options for {@link SessionHandle.flush}. */
|
|
34
|
+
export interface SessionHandleFlushOptions {
|
|
35
|
+
/** Optional cancellation observed before the barrier starts. */
|
|
36
|
+
readonly signal?: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One open channel onto a stored session. A handle is single-owner state, not
|
|
40
|
+
* a shared service: `read` never backtracks below what this handle already
|
|
41
|
+
* observed, a `write` handle reads its own successful appends, and `close()`
|
|
42
|
+
* is the one teardown (idempotent, uncancellable; `Symbol.asyncDispose`
|
|
43
|
+
* delegates to it). Every operation on a closed handle rejects with
|
|
44
|
+
* `SessionHandleClosedError`.
|
|
45
|
+
*
|
|
46
|
+
* Freshness across handles: once an `append` or `flush` resolves on a write
|
|
47
|
+
* handle, every read STARTED afterwards on the same backend instance — on any
|
|
48
|
+
* handle, or through `stat`/`list` — observes at least that prefix.
|
|
49
|
+
* Reads concurrent with a mutation carry no ordering promise beyond the valid
|
|
50
|
+
* contiguous prefix.
|
|
51
|
+
*/
|
|
52
|
+
export interface SessionHandle extends AsyncDisposable {
|
|
53
|
+
/** The stored session this handle addresses. */
|
|
54
|
+
readonly id: SessionId;
|
|
55
|
+
/** The immutable stored header, fixed at `create`/`open`. */
|
|
56
|
+
readonly header: SessionHeader;
|
|
57
|
+
/**
|
|
58
|
+
* Exact fork-inherited prefix length stored with the log; `0` when
|
|
59
|
+
* `header.isSeeded` is false. Storage metadata paired with the header for
|
|
60
|
+
* every body read, never part of the replayable event log.
|
|
61
|
+
*/
|
|
62
|
+
readonly inheritedEventCount: SessionLogOffset;
|
|
63
|
+
/** Whether this handle may mutate the log. */
|
|
64
|
+
readonly access: SessionAccess;
|
|
65
|
+
/**
|
|
66
|
+
* Read a slice of the valid contiguous logical log. The slice is a legal log
|
|
67
|
+
* prefix segment: a torn physical tail is never returned, and repeated reads
|
|
68
|
+
* on this handle never observe an older state than a prior read.
|
|
69
|
+
* @param offset - first logical event seq to include; defaults to `0`.
|
|
70
|
+
* @param length - maximum number of events to return; defaults to the rest
|
|
71
|
+
* of the log. An offset at or past the end returns an empty list.
|
|
72
|
+
* @param options - optional cancellation.
|
|
73
|
+
* @returns the caller-owned outer slice plus the ownership state of its event values.
|
|
74
|
+
*/
|
|
75
|
+
read(offset?: number, length?: number, options?: SessionHandleReadOptions): Promise<SessionHandleReadResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Append a contiguous batch continuing the current logical end. The first
|
|
78
|
+
* event's `seq` MUST equal the stored next-seq. Ordinary appends never
|
|
79
|
+
* rewrite committed events; an explicit persistence `truncate` is the
|
|
80
|
+
* destructive exception. Persistence is best-effort: on resolution the batch is
|
|
81
|
+
* accepted, ordered, and visible to reads on this backend instance, but
|
|
82
|
+
* only a resolved {@link flush} promises it survives a crash — a backend
|
|
83
|
+
* may buffer or batch physical writes behind append. Rejects with
|
|
84
|
+
* `SessionReadOnlyError` on a read handle and `SessionOwnershipLostError`
|
|
85
|
+
* when write ownership is gone.
|
|
86
|
+
* @param events - the contiguous batch, in seq order.
|
|
87
|
+
* @param options - optional cancellation observed before the write starts.
|
|
88
|
+
*/
|
|
89
|
+
append(events: readonly SessionEvent[], options?: SessionHandleAppendOptions): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* The durability barrier — the one operation that promises storage: on
|
|
92
|
+
* resolution every acknowledged append is durable and the session is
|
|
93
|
+
* materialized for other processes; an empty created session becomes
|
|
94
|
+
* durably listable here. Callers that must survive a crash flush; a backend
|
|
95
|
+
* whose `append` already persists on resolution treats this as
|
|
96
|
+
* materialize-if-needed. Rejects with `SessionReadOnlyError` on a read
|
|
97
|
+
* handle.
|
|
98
|
+
* @param options - optional cancellation observed before the barrier starts.
|
|
99
|
+
*/
|
|
100
|
+
flush(options?: SessionHandleFlushOptions): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Release the handle: a read handle frees local resources; a write handle
|
|
103
|
+
* completes pending durability and releases write ownership. Idempotent,
|
|
104
|
+
* asynchronous, and deliberately not cancellable.
|
|
105
|
+
*/
|
|
106
|
+
close(): Promise<void>;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=handle.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,243 +1,204 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Durable session-persistence Service Definition (`ctx.sessionPersistence`). Backends store
|
|
3
3
|
* {@link SessionEvent}s as the event-sourced log and carry non-replayable
|
|
4
|
-
* {@link SessionHeader} metadata separately
|
|
4
|
+
* {@link SessionHeader} metadata separately; callers address one stored
|
|
5
|
+
* session through a {@link SessionHandle} obtained from `create`/`open`.
|
|
5
6
|
* @module @x1a0f3n9/dsh-session-persistence
|
|
6
7
|
*/
|
|
7
8
|
import { Context, Service } from '@deepseek-ai/cordis';
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
9
|
+
import type { SessionEvent, SessionHeader, SessionId, SessionLogOffset, SessionSeqCursor } from '@x1a0f3n9/dsh-session';
|
|
10
|
+
import type { SessionHandle, SessionAccess } from './handle.ts';
|
|
10
11
|
import type { SessionPersistenceRevision } from './revision.ts';
|
|
11
12
|
export type { SessionHeader } from '@x1a0f3n9/dsh-session';
|
|
12
13
|
export { SessionPersistenceRevision } from './revision.ts';
|
|
13
|
-
export {
|
|
14
|
-
|
|
14
|
+
export type { SessionAccess, SessionHandle, SessionHandleAppendOptions, SessionHandleFlushOptions, SessionHandleReadOptions, SessionHandleReadResult, } from './handle.ts';
|
|
15
|
+
export { SessionAlreadyExistsError, SessionAlreadyOwnedError, SessionFormatUnsupportedError, SessionHandleClosedError, SessionOwnershipLostError, SessionPersistenceCorruptionError, SessionPersistenceNotFoundError, SessionReadOnlyError, sessionFormatVersionRefusal, } from './errors.ts';
|
|
16
|
+
export type { SessionLocation } from './errors.ts';
|
|
17
|
+
export { assertContiguous, assertStoredId, assertVersion, materializeAppendBatch, materializeCreateHeader, validateStoredEvents, } from './storage-contract.ts';
|
|
18
|
+
/**
|
|
19
|
+
* Lightweight stored-session observation returned by {@link SessionPersistence.stat}
|
|
20
|
+
* and {@link SessionPersistence.list} without reading the full event log.
|
|
21
|
+
*/
|
|
15
22
|
export interface SessionPersistenceSnapshot {
|
|
16
|
-
/** Detached metadata for one
|
|
17
|
-
header: SessionHeader;
|
|
18
|
-
/** Opaque
|
|
19
|
-
revision: SessionPersistenceRevision;
|
|
23
|
+
/** Detached metadata for one stored session. */
|
|
24
|
+
readonly header: SessionHeader;
|
|
25
|
+
/** Opaque change token; see {@link SessionPersistence.stat}. */
|
|
26
|
+
readonly revision: SessionPersistenceRevision;
|
|
27
|
+
/** Logical event count, when the backend can provide it cheaply from metadata; otherwise absent. */
|
|
28
|
+
readonly eventCount?: number;
|
|
29
|
+
/** Physical artifact byte size, when the backend can provide it cheaply (JSONL); otherwise absent. */
|
|
30
|
+
readonly sizeBytes?: number;
|
|
20
31
|
}
|
|
21
|
-
/**
|
|
32
|
+
/** Options for {@link SessionPersistence.create}. */
|
|
33
|
+
export interface SessionPersistenceCreateOptions {
|
|
34
|
+
/** Optional cancellation observed before backend work starts. */
|
|
35
|
+
readonly signal?: AbortSignal;
|
|
36
|
+
/**
|
|
37
|
+
* Exact fork-inherited prefix length. Required when `header.isSeeded` is
|
|
38
|
+
* true and must be omitted (or `0`) otherwise; the backend refuses a
|
|
39
|
+
* mismatch at create.
|
|
40
|
+
*/
|
|
41
|
+
readonly inheritedEventCount?: SessionLogOffset;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Logical Session header paired with its exact inherited cut for body-bearing
|
|
45
|
+
* storage operations. `isSeeded` marks fork lineage on the header; the
|
|
46
|
+
* numeric cut travels beside it, never inside the replayable event log.
|
|
47
|
+
*/
|
|
22
48
|
export interface SessionStorageMetadata {
|
|
23
49
|
/** Validated immutable Session header. */
|
|
24
50
|
readonly meta: SessionHeader;
|
|
25
51
|
/** Number of leading events inherited from the Session's fork parent. */
|
|
26
52
|
readonly inheritedEventCount: SessionLogOffset;
|
|
27
53
|
}
|
|
28
|
-
/** Immutable logical session
|
|
54
|
+
/** Immutable logical session read: storage metadata plus the complete validated event log. */
|
|
29
55
|
export interface SessionInspection extends SessionStorageMetadata {
|
|
30
|
-
/**
|
|
56
|
+
/** Contiguous validated events from seq 0. */
|
|
31
57
|
readonly events: readonly SessionEvent[];
|
|
32
58
|
}
|
|
33
|
-
/**
|
|
34
|
-
export interface
|
|
35
|
-
/**
|
|
36
|
-
readonly
|
|
37
|
-
/** Valid contiguous stored events at or after {@link fromSeq}; not a complete Session log when the offset is nonzero. */
|
|
38
|
-
readonly events: readonly SessionEvent[];
|
|
59
|
+
/** Options for {@link SessionPersistence.open}. */
|
|
60
|
+
export interface SessionPersistenceOpenOptions {
|
|
61
|
+
/** Optional cancellation observed before backend work starts. */
|
|
62
|
+
readonly signal?: AbortSignal;
|
|
39
63
|
}
|
|
40
|
-
/**
|
|
41
|
-
export
|
|
42
|
-
/**
|
|
43
|
-
readonly
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
readonly
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
/** Options for {@link SessionPersistence.stat}. */
|
|
65
|
+
export interface SessionPersistenceStatOptions {
|
|
66
|
+
/** Optional cancellation for backend metadata reads. */
|
|
67
|
+
readonly signal?: AbortSignal;
|
|
68
|
+
}
|
|
69
|
+
/** Options for {@link SessionPersistence.list}. */
|
|
70
|
+
export interface SessionPersistenceListOptions {
|
|
71
|
+
/** Optional cancellation for backend listing work. */
|
|
72
|
+
readonly signal?: AbortSignal;
|
|
73
|
+
}
|
|
74
|
+
/** Options for {@link SessionPersistence.readHistorySuffix}. */
|
|
75
|
+
export interface SessionHistorySuffixOptions {
|
|
76
|
+
/** Maximum append-surface user/assistant messages the suffix must cover. */
|
|
77
|
+
readonly maxMessages: number;
|
|
78
|
+
/** Exclusive upper bound of an older page; omit for the newest page. */
|
|
79
|
+
readonly beforeSeq?: number;
|
|
80
|
+
/** Inclusive newest seq the page may include; omit for the durable cursor. */
|
|
81
|
+
readonly throughSeq?: number;
|
|
82
|
+
/** Optional cancellation for backend suffix reads. */
|
|
83
|
+
readonly signal?: AbortSignal;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A contiguous tail of one stored log that covers one history page without
|
|
87
|
+
* restoring the whole artifact.
|
|
88
|
+
*/
|
|
89
|
+
export interface SessionHistorySuffix {
|
|
90
|
+
/** Immutable stored header. */
|
|
91
|
+
readonly header: SessionHeader;
|
|
92
|
+
/** Exact inherited prefix length, or `0` when a seeded cut is not in the suffix. */
|
|
93
|
+
readonly inheritedEventCount: SessionLogOffset;
|
|
94
|
+
/** Contiguous events covering the requested page, possibly with interrupted-turn closers. */
|
|
95
|
+
readonly events: SessionEvent[];
|
|
96
|
+
/** Last logical seq in this view, including in-memory closers. */
|
|
97
|
+
readonly cursor: SessionSeqCursor;
|
|
62
98
|
}
|
|
63
|
-
export { DEFAULT_PREPARED_SESSION_CACHE_SIZE, DEFAULT_WRITE_BATCH_MAX_DELAY_MS, MAX_WRITE_BATCH_DELAY_MS, PersistenceCoordinator, SessionFormatUnsupportedError, SessionPersistenceCorruptionError, sessionFormatVersionRefusal, } from './coordinator.ts';
|
|
64
|
-
export type { PersistenceBackend, PersistenceCoordinatorOptions, StoredPrefix, StoredSuffix, } from './coordinator.ts';
|
|
65
99
|
declare module '@deepseek-ai/cordis' {
|
|
66
100
|
interface Context {
|
|
67
101
|
sessionPersistence: SessionPersistence;
|
|
68
102
|
}
|
|
69
103
|
}
|
|
70
104
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
105
|
+
* Durable session storage addressed through per-session handles. Normal
|
|
106
|
+
* writes append to a contiguous log; an explicit destructive tail truncation
|
|
107
|
+
* may rewrite the retained prefix when a backend supports it.
|
|
108
|
+
*
|
|
109
|
+
* Storage semantics shared by every backend: events are contiguous from seq 0;
|
|
110
|
+
* a torn physical tail is never returned to a reader and
|
|
111
|
+
* is truncated by the write path before its first append; reads validate
|
|
112
|
+
* current-format records only and refuse unknown vocabulary fail-closed.
|
|
113
|
+
* `append` persists best-effort; `flush` — per handle or service-wide — is
|
|
114
|
+
* the durability barrier.
|
|
115
|
+
*
|
|
116
|
+
* Visibility: a created session is observable through `stat`/`list`/`open`
|
|
117
|
+
* in this process from the moment `create` resolves, even while a backend
|
|
118
|
+
* defers physical materialization (a pure optimization); other processes see
|
|
119
|
+
* the session only once it materializes, and a session that never
|
|
120
|
+
* materialized before a crash never existed. `SessionHandle.flush` forces
|
|
121
|
+
* materialization.
|
|
122
|
+
*
|
|
123
|
+
* Freshness: once an `append` or `flush` resolves, reads started afterwards
|
|
124
|
+
* on this backend instance observe at least that prefix.
|
|
86
125
|
*/
|
|
87
126
|
export declare abstract class SessionPersistence extends Service {
|
|
88
127
|
constructor(ctx: Context);
|
|
89
128
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* @
|
|
94
|
-
* @
|
|
95
|
-
*/
|
|
96
|
-
abstract locate(meta: SessionHeader): SessionLocation | undefined;
|
|
97
|
-
/**
|
|
98
|
-
* Whether this backend exposes one verbatim raw artifact per session.
|
|
99
|
-
* A backend that declares `true` must override {@link readRaw}.
|
|
129
|
+
* Create a new stored session and take its write ownership.
|
|
130
|
+
* @param header - the immutable header (id, version, cwd, lineage) to store.
|
|
131
|
+
* @param options - optional cancellation.
|
|
132
|
+
* @returns a `write` handle owned by the caller; close it to release ownership.
|
|
133
|
+
* @throws {SessionAlreadyExistsError} when the id already exists.
|
|
100
134
|
*/
|
|
101
|
-
abstract
|
|
135
|
+
abstract create(header: SessionHeader, options?: SessionPersistenceCreateOptions): Promise<SessionHandle>;
|
|
102
136
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* @param
|
|
111
|
-
*
|
|
112
|
-
* @
|
|
113
|
-
* @
|
|
114
|
-
* session is absent.
|
|
115
|
-
* @throws when this backend does not expose per-session raw artifacts.
|
|
137
|
+
* Open an existing stored session.
|
|
138
|
+
*
|
|
139
|
+
* `read` never takes ownership and works while another handle (or process)
|
|
140
|
+
* holds write ownership. `write` atomically claims single-writer ownership;
|
|
141
|
+
* an existing active owner rejects.
|
|
142
|
+
* @param id - the stored session to open.
|
|
143
|
+
* @param access - `read` or `write`.
|
|
144
|
+
* @param options - optional cancellation.
|
|
145
|
+
* @returns the open handle.
|
|
146
|
+
* @throws {SessionPersistenceNotFoundError} when the session does not exist.
|
|
147
|
+
* @throws {SessionAlreadyOwnedError} for `write` when ownership is taken.
|
|
116
148
|
*/
|
|
117
|
-
|
|
149
|
+
abstract open(id: SessionId, access: SessionAccess, options?: SessionPersistenceOpenOptions): Promise<SessionHandle>;
|
|
118
150
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
151
|
+
* Flush every active write handle owned by this service instance in one
|
|
152
|
+
* durability barrier: each handle's routed live events drain durably and
|
|
153
|
+
* its session materializes, exactly as that handle's own
|
|
154
|
+
* `SessionHandle.flush` would. Read handles buffer nothing and are
|
|
155
|
+
* untouched. A handle closed concurrently counts as flushed — close itself
|
|
156
|
+
* drains durably.
|
|
157
|
+
* @returns resolution once every write handle active at the call has flushed.
|
|
158
|
+
* @throws {AggregateError} naming each session whose flush failed; the
|
|
159
|
+
* remaining handles still flush.
|
|
126
160
|
*/
|
|
127
|
-
abstract
|
|
161
|
+
abstract flush(): Promise<void>;
|
|
128
162
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
163
|
+
* Observe one stored session without reading its event log or taking
|
|
164
|
+
* ownership.
|
|
165
|
+
*
|
|
166
|
+
* The snapshot's `revision` is an opaque change token comparable only
|
|
167
|
+
* against revisions from the same service instance and session id: equal
|
|
168
|
+
* revisions may be treated as an unchanged log; unequal revisions promise
|
|
169
|
+
* nothing. Write-ownership churn does not change a revision. It exists for
|
|
170
|
+
* derived read-model caches keyed off `stat`/`list`; it plays no part in
|
|
171
|
+
* open, read, or resume.
|
|
172
|
+
* @param id - the stored session to observe.
|
|
173
|
+
* @param options - optional cancellation.
|
|
174
|
+
* @returns the snapshot, or `undefined` when the session does not exist.
|
|
133
175
|
*/
|
|
134
|
-
|
|
176
|
+
abstract stat(id: SessionId, options?: SessionPersistenceStatOptions): Promise<SessionPersistenceSnapshot | undefined>;
|
|
135
177
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* serializable `event.data` with an error naming the offending event type.
|
|
140
|
-
* A seeded session's first materializing batch must reach its complete
|
|
141
|
-
* inherited prefix.
|
|
142
|
-
* @param id - the session the batch belongs to.
|
|
143
|
-
* @param events - the contiguous batch to persist, in seq order.
|
|
178
|
+
* List every stored session visible to this process, in no promised order.
|
|
179
|
+
* @param options - optional cancellation.
|
|
180
|
+
* @returns one snapshot per stored session.
|
|
144
181
|
*/
|
|
145
|
-
abstract
|
|
182
|
+
abstract list(options?: SessionPersistenceListOptions): Promise<readonly SessionPersistenceSnapshot[]>;
|
|
146
183
|
/**
|
|
147
|
-
*
|
|
184
|
+
* Permanently replace one session's durable event log with an earlier prefix.
|
|
148
185
|
* The caller must apply the matching in-memory truncation only after this
|
|
149
|
-
* promise resolves. Backends
|
|
150
|
-
* @param
|
|
151
|
-
* @param
|
|
152
|
-
|
|
153
|
-
truncate(_session: Session, _length: SessionLogOffset): Promise<void>;
|
|
154
|
-
/**
|
|
155
|
-
* Prepare the exact unpublished Session used by resume. Implementations may
|
|
156
|
-
* reuse object graphs retained by an earlier {@link inspect} after confirming
|
|
157
|
-
* their durable revision is still current; disposal releases an unpublished
|
|
158
|
-
* reservation. Revision retries require the durable log to remain unchanged
|
|
159
|
-
* for one read/check round trip; continuous external writers may delay completion.
|
|
160
|
-
* @param id - persisted session to prepare.
|
|
161
|
-
* @param signal - optional cancellation for preparation work.
|
|
162
|
-
* @returns one owned unpublished Session preparation.
|
|
163
|
-
*/
|
|
164
|
-
prepare(id: SessionId, signal?: AbortSignal): Promise<SessionPreparation>;
|
|
165
|
-
/**
|
|
166
|
-
* Load an immutable balanced logical view and commit any required cold
|
|
167
|
-
* recovery. A complete interrupted final turn is preserved and durably
|
|
168
|
-
* closed with missing tool errors plus any open step and turn boundaries;
|
|
169
|
-
* only a torn final record is discarded. Unknown versions and corruption in
|
|
170
|
-
* the committed prefix reject. Implementations MUST NOT crash-repair an
|
|
171
|
-
* identity still bound to a live Session: a balanced live log may return as a
|
|
172
|
-
* durable snapshot, while an open live turn rejects. Returned values may be
|
|
173
|
-
* shared with immutable live or prepared state and must not be mutated.
|
|
174
|
-
* Revision-based implementations may wait for one stable read/check round trip.
|
|
175
|
-
* @param id - the persisted session to reload.
|
|
176
|
-
* @returns the header and a log ending on a balanced `turn/end`.
|
|
186
|
+
* promise resolves. Backends that do not support rewriting reject loudly.
|
|
187
|
+
* @param _id - the live session whose durable log is being rewritten.
|
|
188
|
+
* @param _length - number of events to retain.
|
|
189
|
+
* @returns resolution after the retained prefix is durable.
|
|
177
190
|
*/
|
|
178
|
-
|
|
191
|
+
truncate(_id: SessionId, _length: SessionLogOffset): Promise<void>;
|
|
179
192
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* already committing or reserved for resume remains exclusive, and inspection
|
|
188
|
-
* may borrow its immutable view. Callers borrow only the immutable header and
|
|
189
|
-
* log. Continuous external writers may delay revision convergence.
|
|
190
|
-
* @param id - the persisted session to inspect.
|
|
191
|
-
* @param signal - optional cancellation for queued and backend read work.
|
|
192
|
-
* @returns the validated header and current logical event log.
|
|
193
|
-
*/
|
|
194
|
-
abstract inspect(id: SessionId, signal?: AbortSignal): Promise<SessionInspection>;
|
|
195
|
-
/**
|
|
196
|
-
* Borrow one exact inspection while retaining any reusable prepared source.
|
|
197
|
-
* A cold observation must pin the exact prepared Session that a later
|
|
198
|
-
* {@link prepare} reserves. Implementations must not degrade this operation
|
|
199
|
-
* to a detached {@link inspect} result.
|
|
200
|
-
* @param id - persisted session to observe.
|
|
201
|
-
* @param signal - optional cancellation for preparation work.
|
|
202
|
-
* @returns a disposable immutable observation.
|
|
203
|
-
*/
|
|
204
|
-
abstract borrowSession(id: SessionId, signal?: AbortSignal): Promise<BorrowedSessionSource>;
|
|
205
|
-
/**
|
|
206
|
-
* Read the stored events from `fromSeq` onward — the read-from-seq
|
|
207
|
-
* primitive for read models that resume from a watermark (e.g. a persisted
|
|
208
|
-
* projection cache folding only the tail past its checkpoint). Unlike
|
|
209
|
-
* {@link inspect}, it is a detached physical suffix read: no preparation
|
|
210
|
-
* cache, torn-tail truncation, synthetic closers, or coordinator-state
|
|
211
|
-
* publication. Only events from the valid contiguous stored prefix are
|
|
212
|
-
* returned, so a torn fragment never reaches the caller. `fromSeq` at or
|
|
213
|
-
* beyond the stored prefix returns an empty event list (never an error).
|
|
214
|
-
* A backend whose medium can seek by seq may read only the suffix;
|
|
215
|
-
* sequential media such as JSONL still parse the whole artifact and skip
|
|
216
|
-
* forward. The primitive bounds what is returned and refolded, not every
|
|
217
|
-
* backend's physical read.
|
|
218
|
-
* @param id - the persisted session to read.
|
|
219
|
-
* @param fromSeq - first event offset to include.
|
|
220
|
-
* @param signal - optional cancellation for queued and backend read work.
|
|
221
|
-
* @returns storage metadata, the requested offset, and stored events with `seq >= fromSeq`.
|
|
222
|
-
*/
|
|
223
|
-
abstract readFrom(id: SessionId, fromSeq: SessionLogOffset, signal?: AbortSignal): Promise<SessionEventSuffix>;
|
|
224
|
-
/**
|
|
225
|
-
* Lightweight listing from metadata, without a full-log parse.
|
|
226
|
-
* @param signal - optional cancellation for backend listing work.
|
|
227
|
-
* @returns one header per materialized session.
|
|
228
|
-
*/
|
|
229
|
-
abstract list(signal?: AbortSignal): Promise<SessionHeader[]>;
|
|
230
|
-
/**
|
|
231
|
-
* List materialized sessions with cheap per-log change tokens.
|
|
232
|
-
*
|
|
233
|
-
* Repeated observations of an unchanged log return the same revision. A
|
|
234
|
-
* successful mutating {@link load} repair changes the next listed revision.
|
|
235
|
-
* Revisions also distinguish independently backed stores so backend-local
|
|
236
|
-
* counters cannot compare equal across different persistence sources.
|
|
237
|
-
* @param signal - optional cancellation for backend snapshot-listing work.
|
|
238
|
-
* @returns one header and opaque revision per materialized session without loading full logs.
|
|
193
|
+
* Read a contiguous tail covering one history page without restoring the
|
|
194
|
+
* whole log. Backends that cannot cheaply decode a suffix return `undefined`
|
|
195
|
+
* so callers fall back to a full observation.
|
|
196
|
+
* @param _id - the stored session to read.
|
|
197
|
+
* @param _options - page bounds and cancellation.
|
|
198
|
+
* @returns the suffix, or `undefined` when this backend has no suffix reader
|
|
199
|
+
* or the stored generation must be migrated first.
|
|
239
200
|
*/
|
|
240
|
-
|
|
201
|
+
readHistorySuffix(_id: SessionId, _options: SessionHistorySuffixOptions): Promise<SessionHistorySuffix | undefined>;
|
|
241
202
|
}
|
|
242
203
|
export default SessionPersistence;
|
|
243
204
|
//# sourceMappingURL=index.d.ts.map
|