Class: ClaudeAgentSDK::SessionStore
- Inherits:
-
Object
- Object
- ClaudeAgentSDK::SessionStore
- Defined in:
- lib/claude_agent_sdk/session_store.rb
Overview
Adapter for mirroring session transcripts to external storage.
The subprocess still writes to local disk; the adapter receives a secondary
copy via SessionStore#append, and resume can materialize from the store
via SessionStore#load when the local file is absent.
Only #append and #load are required. The remaining methods are optional:
implementers may omit them, and the SDK probes for their presence via
SessionStore.implements? before invoking (it never uses is_a? for this —
a duck-typed adapter need not subclass SessionStore). The default
implementations here raise NotImplementedError so subclasses inherit them as
"absent" markers.
All keys/entries cross the adapter boundary as Hashes with STRING keys:
- SessionKey: { 'project_key' => String, 'session_id' => String,
'subpath' => String (optional; omit for the main transcript) }
- entries: raw JSONL transcript objects (opaque pass-through blobs)
- list_sessions result: [{ 'session_id' => String, 'mtime' => Integer }]
- summary entries: { 'session_id', 'mtime', 'data' } (see SessionSummary)
FIBER-NATIVE ADAPTERS (issue #47 phase 3): an adapter whose IO is
entirely Fiber-scheduler-aware may additionally define an optional
callback_scheduling method returning :inline (:thread = default
behavior). The SDK then runs the adapter's timeout-bounded calls in place
on the reactor fiber under a cooperative timeout instead of on a
throwaway thread with a hard Thread#join bound. The declaration covers
EVERY method the SDK invokes on the adapter — append, load,
list_sessions, list_session_summaries, list_subkeys — not just
append/load: resume materialization inlines the listing calls too. Only
the adapter author can make this call — declare :inline ONLY if every
blocking operation in every method yields to the scheduler;
scheduler-opaque blocking stalls every job on the worker AND escapes the
cooperative deadline. A timed-out inline call is interrupted at its next
suspension point (ensure blocks run) rather than abandoned. The
cancellation reaches only the adapter's own fiber — work the adapter
offloaded (descendant tasks, an already-issued remote write) may still
land afterwards — so timed-out appends are NOT retried (same as thread
mode) and a cancelled append may remain permanently half-applied in the
store. The drop is surfaced (MirrorErrorMessage, batches_dropped?) and
the local transcript remains the source of truth; the
dedupe-by-entry-uuid recommendation above stays advisory. The method is deliberately NOT defined here: the SDK probes
respond_to?(:callback_scheduling) (see
SessionStores.store_callback_scheduling), so pure duck-typed adapters
stay minimal, and an app can opt a third-party fiber-native adapter in
via a singleton method (def store.callback_scheduling = :inline).
Direct Known Subclasses
Class Method Summary collapse
-
.implements?(store, method) ⇒ Boolean
True if
storeoverridesmethodrather than inheriting the base implementation that raises NotImplementedError.
Instance Method Summary collapse
-
#append(_key, _entries) ⇒ Object
Mirror a batch of transcript entries.
-
#delete(_key) ⇒ Object
Delete a session.
-
#list_session_summaries(_project_key) ⇒ Object
Return incrementally-maintained summaries for all sessions in one call.
-
#list_sessions(_project_key) ⇒ Object
List sessions for a project_key as [{ 'session_id', 'mtime' }].
-
#list_subkeys(_key) ⇒ Object
List all subpath keys under a session (e.g. subagent transcripts).
-
#load(_key) ⇒ Object
Load a full session for resume, or nil for a key that was never written.
Class Method Details
.implements?(store, method) ⇒ Boolean
True if store overrides method rather than inheriting the base
implementation that raises NotImplementedError. Works for both subclasses
and duck-typed adapters (whose method owner is their own class).
65 66 67 68 69 70 71 |
# File 'lib/claude_agent_sdk/session_store.rb', line 65 def self.implements?(store, method) return false unless store.respond_to?(method) store.method(method).owner != SessionStore rescue NameError false end |
Instance Method Details
#append(_key, _entries) ⇒ Object
Mirror a batch of transcript entries. Called AFTER the subprocess's local write succeeds. Required.
Appends for a given key are normally serialized by the batcher, but if an #append exceeds the send timeout the batcher abandons that (still-running) call and proceeds, so a later #append for the SAME key can overlap it. Implementations must therefore be thread-safe per key (a per-call connection — Postgres/Redis/etc. — satisfies this) and should dedupe by entry when present, since a retried/overlapping batch may repeat a prior write.
83 84 85 |
# File 'lib/claude_agent_sdk/session_store.rb', line 83 def append(_key, _entries) raise NotImplementedError, "#{self.class} must implement #append" end |
#delete(_key) ⇒ Object
Delete a session. Deleting a main-transcript key (no subpath) must cascade to all subkeys. Optional — if unimplemented, deletion is a no-op.
108 109 110 |
# File 'lib/claude_agent_sdk/session_store.rb', line 108 def delete(_key) raise NotImplementedError end |
#list_session_summaries(_project_key) ⇒ Object
Return incrementally-maintained summaries for all sessions in one call. Optional — if unimplemented, list_sessions_from_store falls back to list_sessions + per-session load.
102 103 104 |
# File 'lib/claude_agent_sdk/session_store.rb', line 102 def list_session_summaries(_project_key) raise NotImplementedError end |
#list_sessions(_project_key) ⇒ Object
List sessions for a project_key as [{ 'session_id', 'mtime' }]. Optional — if unimplemented, list_sessions_from_store raises.
95 96 97 |
# File 'lib/claude_agent_sdk/session_store.rb', line 95 def list_sessions(_project_key) raise NotImplementedError end |
#list_subkeys(_key) ⇒ Object
List all subpath keys under a session (e.g. subagent transcripts). Optional — if unimplemented, resume only materializes the main transcript.
114 115 116 |
# File 'lib/claude_agent_sdk/session_store.rb', line 114 def list_subkeys(_key) raise NotImplementedError end |
#load(_key) ⇒ Object
Load a full session for resume, or nil for a key that was never written. Required.
89 90 91 |
# File 'lib/claude_agent_sdk/session_store.rb', line 89 def load(_key) raise NotImplementedError, "#{self.class} must implement #load" end |