Update docs and diagrams for cluster-scale schema changes

- StorageBackend protocol: document 5 new workstream methods (26 total)
- Session ID: 12-char hex → 32-char full UUID in API reference
- /health endpoint: add node_id field to response docs
- sessions table: document node_id and ws_id columns
- Bridge node_id: document server-owned identity with /health retrieval
- Regenerate storage architecture PNG from updated PlantUML
This commit is contained in:
Patrick Buckley
2026-03-04 06:12:31 -08:00
parent a20a058c59
commit 7adda343fc
4 changed files with 34 additions and 12 deletions
+6 -2
View File
@@ -394,12 +394,14 @@ Each session object:
| Field | Type | Description |
|-----------------|-------------|--------------------------------------------|
| `session_id` | string | Unique 12-char hex session identifier |
| `session_id` | string | Unique 32-char hex UUID session identifier |
| `alias` | string/null | User-assigned short name |
| `title` | string/null | LLM-generated title |
| `created` | string | ISO timestamp of session creation |
| `updated` | string | ISO timestamp of last message |
| `message_count` | int | Number of messages in the session |
| `node_id` | string/null | Server node that created the session |
| `ws_id` | string/null | Workstream the session belongs to |
---
@@ -692,7 +694,8 @@ liveness probes.
```json
{
"status": "ok",
"version": "0.3.0",
"version": "0.3.5",
"node_id": "worker-01_a3f2",
"uptime_seconds": 3614.72,
"model": "llama-3.1-70b-instruct",
"workstreams": {
@@ -714,6 +717,7 @@ liveness probes.
|-------|------|-------------|
| `status` | string | `"ok"` or `"degraded"` (degraded when backend unreachable) |
| `version` | string | turnstone server version |
| `node_id` | string | Server-generated node identity (`{hostname}_{4hex}`) |
| `uptime_seconds` | number | Seconds since the server process started |
| `model` | string | Model name detected or configured at startup |
| `workstreams.total` | integer | Total active workstreams |
+15 -5
View File
@@ -713,7 +713,7 @@ and are the single source of truth for both backends and Alembic migrations.
| Method | Purpose |
|--------|---------|
| `register_session(session_id, title)` | Create a sessions row (no-op if exists) |
| `register_session(session_id, title, node_id, ws_id)` | Create a sessions row (no-op if exists) |
| `save_message(session_id, role, content, ...)` | Log a message to conversations |
| `load_session_messages(session_id)` | Reconstruct OpenAI message format from DB rows |
| `list_sessions(limit)` | List sessions with >=1 message, ordered by updated DESC |
@@ -725,6 +725,11 @@ and are the single source of truth for both backends and Alembic migrations.
| `set_session_alias(session_id, alias)` | Set user-friendly alias (returns False if taken) |
| `get_session_name(session_id)` | Return alias if set, else title, else None |
| `update_session_title(session_id, title)` | Set/update LLM-generated title |
| `register_workstream(ws_id, node_id, name, state)` | Create a workstreams row (no-op if exists) |
| `update_workstream_state(ws_id, state)` | Update workstream state and bump timestamp |
| `update_workstream_name(ws_id, name)` | Update workstream display name |
| `delete_workstream(ws_id)` | Delete a workstream row |
| `list_workstreams(node_id, limit)` | List workstreams, optionally by node |
| `kv_get(key)` / `kv_set(key, value)` / `kv_delete(key)` | Generic key-value store (backs memories table) |
| `kv_list()` / `kv_search(query)` | List or search key-value pairs |
| `search_history(query, limit)` | Full-text search (FTS5 on SQLite, tsvector on PostgreSQL) |
@@ -745,9 +750,11 @@ Environment variables: `TURNSTONE_DB_BACKEND`, `TURNSTONE_DB_URL`, `TURNSTONE_DB
### Session Persistence and Resume
Each `ChatSession` generates a 12-char hex `_session_id` on creation and
registers it in the `sessions` table. Messages are saved to `conversations`
as they happen via `save_message()`.
Each `ChatSession` generates a full 32-char hex UUID `_session_id` on creation
and registers it in the `sessions` table with the server's `node_id` and the
owning `ws_id`. Messages are saved to `conversations` as they happen via
`save_message()`. Workstreams are persisted to the `workstreams` table on
creation, with state changes tracked via `update_workstream_state()`.
**Auto-titling:** After the first complete exchange (user message + assistant
response), a background thread calls the LLM with a title-generation prompt
@@ -1037,7 +1044,10 @@ a response or the approval timeout (default 3600s / 1 hour) expires.
`ws_id` for active sends. When the global SSE reports `ws_state → idle` for a tracked
workstream, the bridge emits a synthetic `TurnCompleteEvent` with the correlation ID.
**Multi-node routing:** Each bridge has a `node_id` (defaults to hostname) and BLPOPs
**Multi-node routing:** Each bridge retrieves its `node_id` from the server's
`/health` endpoint on startup (with exponential backoff retry). The server
generates the `node_id` (`{hostname}_{4hex}`) and is the sole authority for
node identity. The bridge BLPOPs
from both `turnstone:inbound:{node_id}` (directed, priority) and `turnstone:inbound` (shared).
Messages with `target_node` set are pushed to the target's per-node queue. Messages
for existing workstreams are auto-routed via `turnstone:ws:{ws_id}` ownership keys in Redis.
+11 -3
View File
@@ -13,7 +13,7 @@ skinparam class {
' -- Protocol --
interface "StorageBackend" as SB <<protocol>> {
+register_session(session_id, title)
+register_session(session_id, title, node_id, ws_id)
+save_message(session_id, role, content, ...)
+load_session_messages(session_id) → list[dict]
+list_sessions(limit) → list
@@ -25,6 +25,11 @@ interface "StorageBackend" as SB <<protocol>> {
+set_session_alias(session_id, alias) → bool
+get_session_name(session_id) → str | None
+update_session_title(session_id, title)
+register_workstream(ws_id, node_id, name, state)
+update_workstream_state(ws_id, state)
+update_workstream_name(ws_id, name)
+delete_workstream(ws_id) → bool
+list_workstreams(node_id, limit) → list
+kv_get(key) → str | None
+kv_set(key, value) → str | None
+kv_delete(key) → bool
@@ -58,7 +63,8 @@ class "_schema.py" as Schema <<schema>> {
+metadata: MetaData
+memories: Table
+conversations: Table
+sessions: Table
+sessions: Table (node_id, ws_id)
+workstreams: Table (node_id, state)
+session_config: Table
--
SQLAlchemy Core
@@ -94,9 +100,11 @@ class "memory.py" as Facade <<facade>> {
+register_session()
+save_message()
+load_session_messages()
+register_workstream()
+update_workstream_state()
+save_memory() / delete_memory()
+search_memories()
+... (all 18 functions)
+... (all 22 functions)
--
Thin delegation to
get_storage()
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0c615984373b4893b6cc5755604f137541e9d391862122746a4fcbae63543563
size 201041
oid sha256:bd776a34b50d3fe194e2a34d3b4d04ec71af31e1154b5fc98223636b1844e6b8
size 226686