Class: RubynCode::Memory::SessionPersistence
- Inherits:
-
Object
- Object
- RubynCode::Memory::SessionPersistence
- Defined in:
- lib/rubyn_code/memory/session_persistence.rb
Overview
Saves and restores full conversation sessions to SQLite, enabling session continuity across process restarts and session browsing.
Constant Summary collapse
- JSON_ATTRS =
%i[metadata messages].freeze
- SIMPLE_ATTRS =
%i[title status model].freeze
Instance Method Summary collapse
-
#delete_session(session_id) ⇒ void
Deletes a session permanently.
-
#initialize(db) ⇒ SessionPersistence
constructor
A new instance of SessionPersistence.
-
#list_sessions(project_path: nil, status: nil, limit: 20) ⇒ Array<Hash>
Lists sessions, optionally filtered by project and/or status.
-
#load_session(session_id) ⇒ Hash?
Loads a session by ID.
-
#save_session(session_id:, project_path:, messages:, **opts) ⇒ void
Persists a complete session snapshot.
-
#update_session(session_id, **attrs) ⇒ void
Updates session attributes.
Constructor Details
#initialize(db) ⇒ SessionPersistence
Returns a new instance of SessionPersistence.
12 13 14 15 16 17 18 19 |
# File 'lib/rubyn_code/memory/session_persistence.rb', line 12 def initialize(db) @db = db # Per-session journal bookkeeping: how many messages are already # persisted and their object identities, so append-only saves can be # detected without comparing message contents. @journal_state = {} ensure_table end |
Instance Method Details
#delete_session(session_id) ⇒ void
This method returns an undefined value.
Deletes a session permanently.
117 118 119 120 |
# File 'lib/rubyn_code/memory/session_persistence.rb', line 117 def delete_session(session_id) clear_journal(session_id) @db.execute('DELETE FROM sessions WHERE id = ?', [session_id]) end |
#list_sessions(project_path: nil, status: nil, limit: 20) ⇒ Array<Hash>
Lists sessions, optionally filtered by project and/or status.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/rubyn_code/memory/session_persistence.rb', line 79 def list_sessions(project_path: nil, status: nil, limit: 20) where_clause, params = build_list_filters(project_path, status) params << limit rows = @db.query(<<~SQL, params).to_a SELECT id, project_path, title, model, status, metadata, created_at, updated_at FROM sessions #{where_clause} ORDER BY updated_at DESC LIMIT ? SQL rows.map { |row| row_to_session_summary(row) } end |
#load_session(session_id) ⇒ Hash?
Loads a session by ID.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rubyn_code/memory/session_persistence.rb', line 51 def load_session(session_id) rows = @db.query( 'SELECT * FROM sessions WHERE id = ?', [session_id] ).to_a return nil if rows.empty? row = rows.first = parse_json_array(row['messages']) += (session_id) if .is_a?(Array) { messages: , metadata: parse_json_hash(row['metadata']), title: row['title'], model: row['model'], status: row['status'], project_path: row['project_path'], created_at: row['created_at'], updated_at: row['updated_at'] } end |
#save_session(session_id:, project_path:, messages:, **opts) ⇒ void
This method returns an undefined value.
Persists a complete session snapshot.
Hot-path friendly: when the messages array has only grown since the last save for this session, the new messages are appended to the messages journal table instead of rewriting the whole JSON blob. The blob is only rewritten when history was replaced (compaction, undo, resume) or on the first save of a process.
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rubyn_code/memory/session_persistence.rb', line 33 def save_session(session_id:, project_path:, messages:, **opts) if appendable?(session_id, ) append_to_journal(session_id, , opts) else snapshot_session(session_id, project_path, , opts) end remember_journal_state(session_id, ) rescue StandardError # Journal append can fail (e.g. role CHECK constraint on legacy # schemas) — fall back to a full snapshot. snapshot_session(session_id, project_path, , opts) remember_journal_state(session_id, ) end |
#update_session(session_id, **attrs) ⇒ void
This method returns an undefined value.
Updates session attributes.
99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/rubyn_code/memory/session_persistence.rb', line 99 def update_session(session_id, **attrs) return if attrs.empty? sets, params = build_update_clauses(attrs) return if sets.empty? sets << 'updated_at = ?' params << Time.now.utc.strftime('%Y-%m-%d %H:%M:%S') params << session_id @db.execute("UPDATE sessions SET #{sets.join(', ')} WHERE id = ?", params) clear_journal(session_id) if attrs.key?(:messages) end |