From c13a39317e9dc4db30cd2955372a874d09ac4578 Mon Sep 17 00:00:00 2001 From: vegard Date: Tue, 17 Mar 2026 12:49:50 +0100 Subject: [PATCH] =?UTF-8?q?Fullf=C3=B8r=20oppgave=202.3:=20STDB-klient,=20?= =?UTF-8?q?warmup=20og=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fiks NULL-håndtering i warmup (COALESCE for title/content/created_by) - Renere health check (delete nonexistent node i stedet for create+delete) - Dokumenter HTTP API-format og warmup-flyt i erfaringer - Lagre STDB-token i server .env - Republiser STDB-modul etter containerrestart Verifisert: warmup laster 2 noder + 1 edge, /health viser stdb=connected. Co-Authored-By: Claude Opus 4.6 --- docs/erfaringer/spacetimedb_integrasjon.md | 50 ++++++++++++++++++++++ maskinrommet/src/main.rs | 14 ++---- maskinrommet/src/warmup.rs | 3 +- tasks.md | 3 +- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/docs/erfaringer/spacetimedb_integrasjon.md b/docs/erfaringer/spacetimedb_integrasjon.md index 0078a65..4e6d0d9 100644 --- a/docs/erfaringer/spacetimedb_integrasjon.md +++ b/docs/erfaringer/spacetimedb_integrasjon.md @@ -185,3 +185,53 @@ Worker som gjør AI-behandling av meldinger: 4. Kaller `ai_update_message` reducer → SpacetimeDB oppdaterer body/metadata/edited_at atomisk, lagrer revisjon, legger outbox-entry 5. Sync-worker persisterer til PG via `ai_update` action 6. Ved feil: `clear_ai_processing` reducer rydder flagget + +## 11. HTTP API for å kalle reducere fra Rust (maskinrommet) + +SpacetimeDB eksponerer et HTTP JSON API for å kalle reducere server-side. +Maskinrommet bruker `reqwest` (allerede en avhengighet) — ingen STDB SDK nødvendig. + +### Endepunkt + +``` +POST /v1/database/{database_name}/call/{reducer_name} +Authorization: Bearer {stdb_token} +Content-Type: application/json + +{ + "param1": "verdi1", + "param2": "verdi2" +} +``` + +### Viktige detaljer + +- **Navngitte parametre:** Body er et JSON-objekt med nøkler som matcher + reducer-parameternavn, IKKE en `{"args": [...]}` array. +- **Token:** Opprettes via `POST /v1/identity` → `{"identity": "...", "token": "..."}`. + Token er en JWT signert med serverens ES256-nøkkel. Ny server = ny nøkkel = nye tokens. +- **Suksess:** HTTP 200 med tom body. +- **Reducer-feil:** HTTP 200 med `Err(String)` — feilmeldingen er i body. +- **Valideringsfeil:** HTTP 400 med beskrivende feilmelding. +- **Auth-feil:** HTTP 401/403. + +### Token-håndtering ved containerrestart + +Hvis SpacetimeDB-containeren gjenskapes (data slettet), må: +1. Ny identitet opprettes via `POST /v1/identity` +2. Modulen republiseres med `spacetime publish` +3. STDB-tokenet i `.env` oppdateres + +Maskinrommet kan automatisk opprette en ny identitet ved oppstart hvis +`SPACETIMEDB_TOKEN` ikke er satt, men denne identiteten vil ikke ha +tilgang til en eksisterende database. Bruk derfor alltid et stabilt token. + +### Warmup via HTTP API + +Maskinrommet gjør warmup (PG → STDB) ved oppstart: +1. `clear_all` — tøm STDB (unngå duplikater ved restart) +2. Last alle noder fra PG, kall `create_node` for hver +3. Last alle edges fra PG, kall `create_edge` for hver + +NULLable PG-kolonner (title, content, created_by) må håndteres med +`COALESCE` i SQL-spørringen — STDB-modulen bruker `String`, ikke `Option`. diff --git a/maskinrommet/src/main.rs b/maskinrommet/src/main.rs index ed3a648..b199fc5 100644 --- a/maskinrommet/src/main.rs +++ b/maskinrommet/src/main.rs @@ -127,16 +127,10 @@ async fn health(State(state): State) -> Result, S .await .map_err(|_| StatusCode::SERVICE_UNAVAILABLE)?; - // Sjekk STDB ved å kalle clear_all med en ufarlig test - // (vi bruker en enkel healthcheck-reducer i fremtiden) - let stdb_status = match state.stdb.create_node( - "__healthcheck__", "system", "", "", "hidden", "{}", "", - ).await { - Ok(()) => { - // Rydd opp - let _ = state.stdb.delete_node("__healthcheck__").await; - "connected" - } + // STDB helsesjekk: prøv å slette en ikke-eksisterende node. + // Kallet når STDB og returnerer ok (noop), men feiler ved nettverksfeil. + let stdb_status = match state.stdb.delete_node("__healthcheck_nonexistent__").await { + Ok(()) => "connected", Err(_) => "unavailable", }; diff --git a/maskinrommet/src/warmup.rs b/maskinrommet/src/warmup.rs index d25f30e..17388e0 100644 --- a/maskinrommet/src/warmup.rs +++ b/maskinrommet/src/warmup.rs @@ -19,7 +19,8 @@ pub async fn run(db: &PgPool, stdb: &StdbClient) -> Result( - "SELECT id, node_kind::text, title, content, visibility::text, \ + "SELECT id, node_kind::text, COALESCE(title, '') as title, \ + COALESCE(content, '') as content, visibility::text, \ COALESCE(metadata::text, '{}') as metadata, \ created_at, COALESCE(created_by::text, '') as created_by \ FROM nodes ORDER BY created_at" diff --git a/tasks.md b/tasks.md index 9fdcd95..15dddc9 100644 --- a/tasks.md +++ b/tasks.md @@ -53,8 +53,7 @@ Uavhengige faser kan fortsatt plukkes. - [x] 2.1 Rust-prosjekt: opprett `maskinrommet/` med axum, tokio, sqlx (PG), serde. Dockerfile. Kompilerer og starter. Ref: `docs/retninger/maskinrommet.md`. - [x] 2.2 Auth-middleware: valider Authentik JWT-tokens, slå opp `auth_identities` → node_id. Returner 401 for ugyldige tokens. -- [~] 2.3 SpacetimeDB-klient i maskinrommet: koble til STDB, skriv noder og edges via reducers. - > Påbegynt: 2026-03-17T12:35 +- [x] 2.3 SpacetimeDB-klient i maskinrommet: koble til STDB, skriv noder og edges via reducers. - [ ] 2.4 Skrivestien: `POST /intentions/create_node` — valider, skriv STDB (instant), spawn async PG-skriving. Returner node_id umiddelbart. - [ ] 2.5 Flere intensjoner: `create_edge`, `update_node`, `delete_node`. Validering av tilgang (created_by eller owner/admin-edge). - [ ] 2.6 Docker Compose: legg maskinrommet inn i server-stacken. Intern nettverkstilgang til PG og STDB.