terret-store-sqlite 0.1.0

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/terret/store/sqlite.rb +78 -0
  3. metadata +75 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: deca4043ba1082b662376023c97027ae2f4f2a917c45cdc9561b7ab6cd68eb9c
4
+ data.tar.gz: f9e3b51ee478574126bf02e7e1338a64fd7eeeabf5fdf7c7fbe8aba363ccbf03
5
+ SHA512:
6
+ metadata.gz: b8a023c93e4c19877279820949f8f7e0f75ecc62a58347bf77300c4a503af8e08ae51838034ebcd6beaec72c6c30980b3b8ed9cc63eb6e2233d354773cb9b52a
7
+ data.tar.gz: 87910a8fa2db133ea0a25d7e2c864303cea11a694649a0ea041c2d5a5a891e2c26bfd8c046d5f366693a8ce1aba53fb59b233da08a43c6e07f22f6b9dcda1973
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "terret"
5
+ rescue LoadError
6
+ require_relative "../../../../terret-core/lib/terret" # monorepo path source
7
+ end
8
+ require "sqlite3"
9
+ require "json"
10
+ require "time"
11
+ require "fileutils"
12
+
13
+ module Terret
14
+ module Store
15
+ # SQLite provider: the durable default for long-lived processes. WAL for
16
+ # concurrent readers, busy_timeout instead of hand-rolled retries, one
17
+ # row per event keyed (session_id, seq). Appends are synchronous; the
18
+ # per-session writer task from plan §8 is deferred until many-agent
19
+ # load exists.
20
+ class SQLite < Hames::Service
21
+ service_key :session_store
22
+ config_schema path: { type: String, required: true,
23
+ doc: "SQLite database file for the append-only session log" }
24
+
25
+ SCHEMA = <<~SQL
26
+ CREATE TABLE IF NOT EXISTS events (
27
+ session_id TEXT NOT NULL,
28
+ seq INTEGER NOT NULL,
29
+ id TEXT NOT NULL,
30
+ at TEXT NOT NULL,
31
+ type TEXT NOT NULL,
32
+ payload TEXT NOT NULL,
33
+ PRIMARY KEY (session_id, seq)
34
+ )
35
+ SQL
36
+
37
+ def start(_ctx)
38
+ @db ||= begin
39
+ path = config.fetch(:path)
40
+ FileUtils.mkdir_p(File.dirname(path))
41
+ db = SQLite3::Database.new(path)
42
+ db.busy_timeout = 5_000
43
+ db.execute("PRAGMA journal_mode=WAL")
44
+ db.execute(SCHEMA)
45
+ db
46
+ end
47
+ end
48
+
49
+ def stop(_ctx)
50
+ @db&.close
51
+ @db = nil
52
+ end
53
+
54
+ def append(event)
55
+ @db.execute(
56
+ "INSERT INTO events (session_id, seq, id, at, type, payload) VALUES (?, ?, ?, ?, ?, ?)",
57
+ [event.session_id, event.seq, event.id, event.at.iso8601(6),
58
+ event.type, JSON.generate(event.payload)]
59
+ )
60
+ end
61
+
62
+ def read(session_id, from_seq: 0)
63
+ rows = @db.execute(
64
+ "SELECT id, seq, at, type, payload FROM events WHERE session_id = ? AND seq >= ? ORDER BY seq",
65
+ [session_id, from_seq]
66
+ )
67
+ rows.map do |id, seq, at, type, payload|
68
+ SessionEvent.new(id:, session_id:, seq:, at: Time.iso8601(at), type: type,
69
+ payload: JSON.parse(payload, symbolize_names: true))
70
+ end
71
+ end
72
+
73
+ def session_ids
74
+ @db.execute("SELECT DISTINCT session_id FROM events ORDER BY session_id").flatten
75
+ end
76
+ end
77
+ end
78
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: terret-store-sqlite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Obie Fernandez
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: terret-core
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: sqlite3
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.9'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.9'
40
+ description: 'Durable session persistence for Terret: the append-only session log
41
+ stored one event per row in SQLite (WAL mode), behind the ctx[:session_store] seam,
42
+ so sessions survive process restarts with byte-identical derived context.'
43
+ email:
44
+ - obiefernandez@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - lib/terret/store/sqlite.rb
50
+ homepage: https://terret.org
51
+ licenses:
52
+ - MIT
53
+ metadata:
54
+ homepage_uri: https://terret.org
55
+ source_code_uri: https://github.com/terret-org/terret
56
+ bug_tracker_uri: https://github.com/terret-org/terret/issues
57
+ rubygems_mfa_required: 'true'
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '4.0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubygems_version: 4.0.16
73
+ specification_version: 4
74
+ summary: SQLite session store for the Terret agent harness
75
+ test_files: []