browser_control/registry/
schema.rs1use anyhow::{Context, Result};
4
5const SCHEMA: &str = r#"
6CREATE TABLE IF NOT EXISTS browsers (
7 name TEXT PRIMARY KEY,
8 kind TEXT NOT NULL,
9 engine TEXT NOT NULL,
10 pid INTEGER NOT NULL,
11 endpoint TEXT NOT NULL,
12 port INTEGER NOT NULL,
13 profile_dir TEXT NOT NULL,
14 executable TEXT NOT NULL,
15 headless INTEGER NOT NULL,
16 started_at TEXT NOT NULL
17);
18CREATE INDEX IF NOT EXISTS browsers_kind_started ON browsers(kind, started_at DESC);
19
20-- One scratch tab per browser. Used by lock-free ops (eval/fetch with no
21-- explicit tab) so they never touch a user-visible tab. The single-row
22-- shape is deliberate: concurrent CLI calls share the same scratch row
23-- (CDP allows multiple sessions per target), and recovery just rewrites
24-- target_id when the existing scratch is dead.
25CREATE TABLE IF NOT EXISTS scratches (
26 browser_name TEXT PRIMARY KEY,
27 target_id TEXT NOT NULL,
28 last_used_at_epoch_s INTEGER NOT NULL
29);
30
31-- Named tabs, addressed as `<browser>/<name>` across the CLI. `daemon_created`
32-- distinguishes tabs the CLI opened (eligible for sweep / LRU recycle) from
33-- tabs adopted from the user (kept verbatim, never GC'd).
34CREATE TABLE IF NOT EXISTS tabs (
35 browser_name TEXT NOT NULL,
36 name TEXT NOT NULL,
37 target_id TEXT NOT NULL,
38 last_url TEXT NOT NULL,
39 last_used_at_epoch_s INTEGER NOT NULL,
40 daemon_created INTEGER NOT NULL,
41 PRIMARY KEY (browser_name, name)
42);
43CREATE INDEX IF NOT EXISTS tabs_lru ON tabs(browser_name, daemon_created, last_used_at_epoch_s);
44
45-- Firefox BiDi allows one session per browser. This table arbitrates among
46-- concurrent CLI processes: holder_pid is the winning process, released
47-- on Drop (DELETE WHERE browser_name=? AND holder_pid=?). Stale rows from
48-- crashed CLIs are evicted on acquire via pid_alive().
49CREATE TABLE IF NOT EXISTS bidi_locks (
50 browser_name TEXT PRIMARY KEY,
51 holder_pid INTEGER NOT NULL,
52 acquired_at_epoch_s INTEGER NOT NULL
53);
54
55-- Foreground emulation holders (ADR-004): one detached
56-- `browser-control tab foreground-hold` process per emulated tab. `pid` is
57-- the holder; rows whose pid is dead are evicted on read.
58CREATE TABLE IF NOT EXISTS foreground_holders (
59 browser_name TEXT NOT NULL,
60 target_id TEXT NOT NULL,
61 pid INTEGER NOT NULL,
62 started_at_epoch_s INTEGER NOT NULL,
63 expires_at_epoch_s INTEGER NOT NULL,
64 PRIMARY KEY (browser_name, target_id)
65);
66"#;
67
68pub fn apply(conn: &rusqlite::Connection) -> Result<()> {
70 conn.execute_batch(SCHEMA)
71 .context("applying registry schema")?;
72 Ok(())
73}