From 8e80102f6bf295381e7cc9066d8fd56ff5091cd9 Mon Sep 17 00:00:00 2001 From: vegard Date: Wed, 18 Mar 2026 12:26:33 +0000 Subject: [PATCH] =?UTF-8?q?Fullf=C3=B8r=20oppgave=2022.2:=20Frontend-migre?= =?UTF-8?q?ring=20fra=20SpacetimeDB=20til=20portvokteren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frontend bruker nå kun portvokterens WebSocket for sanntidsdata. SpacetimeDB-klienten er erstattet med en enkel WebSocket-klient som kobler til /ws-endepunktet og oppdaterer reactive stores direkte. Frontend-endringer: - Nye lokale typer (types.ts) erstatter STDB module_bindings - connection.svelte.ts: WebSocket til portvokteren med auto-reconnect - stores.svelte.ts: Prosesserer WS-meldinger (initial_sync + events) - MixerTrait: STDB-reducers erstattet med HTTP API-kall - api.ts: Nye mixer-endepunkter (create, gain, mute, effect, role) - +layout.svelte: Fjernet dual-tilkobling, kun portvokterens WS - pg-ws.svelte.ts: Slettet (erstattet av connection.svelte.ts) Dokumentasjon: - datalaget.md: Fase M1+M2 markert som fullført - api_grensesnitt.md: Oppdatert arkitekturdiagram, nye mixer-endepunkter --- docs/infra/api_grensesnitt.md | 83 ++--- docs/retninger/datalaget.md | 20 +- frontend/src/lib/api.ts | 67 ++++ .../lib/components/traits/MixerTrait.svelte | 70 +++-- frontend/src/lib/mixer.ts | 2 +- .../src/lib/spacetime/connection.svelte.ts | 173 ++++++----- frontend/src/lib/spacetime/index.ts | 7 +- frontend/src/lib/spacetime/pg-ws.svelte.ts | 119 -------- frontend/src/lib/spacetime/stores.svelte.ts | 285 +++++++++--------- frontend/src/lib/spacetime/types.ts | 102 +++++++ frontend/src/routes/+layout.svelte | 18 +- tasks.md | 3 +- 12 files changed, 506 insertions(+), 443 deletions(-) delete mode 100644 frontend/src/lib/spacetime/pg-ws.svelte.ts create mode 100644 frontend/src/lib/spacetime/types.ts diff --git a/docs/infra/api_grensesnitt.md b/docs/infra/api_grensesnitt.md index 0a5311e..c372d19 100644 --- a/docs/infra/api_grensesnitt.md +++ b/docs/infra/api_grensesnitt.md @@ -7,8 +7,7 @@ Maskinrommet eier alle skrivinger: det validerer, skriver til PG, og orkestrerer konsekvenser. Sanntid: PG LISTEN/NOTIFY → maskinrommet → WebSocket `/ws` → frontend. -SpacetimeDB er under utfasing — frontend kobler til begge i parallell -under verifiseringsfasen (Fase M1). +SpacetimeDB er under utfasing — frontend bruker kun portvokterens WebSocket (Fase M2). Tunge spørringer (søk, statistikk, graftraversering) går via maskinrommet → PG. ## 2. Kommunikasjonskart @@ -20,40 +19,38 @@ Tunge spørringer (søk, statistikk, graftraversering) går via maskinrommet → │ │ │ HTTP (intensjoner) │ WebSocket (sanntid) ▼ ▼ -┌──────────────────────┐ ┌──────────────────┐ -│ Maskinrommet (Rust) │ │ SpacetimeDB │ -│ axum HTTP API │ │ │ -│ │ │ - Hele grafen │ -│ Ansvar: │ │ - Push til │ -│ - Validere │ │ klienter │ -│ - Skrive STDB+PG │ │ │ -│ - Orkestrere │ └──────────────────┘ -│ - Tunge spørringer │ -│ - Bakgrunnsjobber │ -└──┬─────┬─────┬───────┘ - │ │ │ - ▼ ▼ ▼ -┌─────┐┌─────┐┌─────────────┐ -│ PG ││STDB ││ Whisper, │ -│ ││ ││ LiteLLM, │ -│ ││ ││ LiveKit ... │ -└─────┘└─────┘└─────────────┘ +┌──────────────────────────────────────┐ +│ Maskinrommet / Portvokteren (Rust) │ +│ axum HTTP API + WebSocket │ +│ │ +│ Ansvar: │ +│ - Validere intensjoner │ +│ - Skrive til PG │ +│ - Orkestrere bakgrunnsjobber │ +│ - Tunge spørringer │ +│ - Sanntid via PG LISTEN → WS │ +└──┬─────────────┬─────────────────────┘ + │ │ + ▼ ▼ +┌─────┐ ┌─────────────┐ +│ PG │ │ Whisper, │ +│ │ │ LiteLLM, │ +│ │ │ LiveKit ... │ +└─────┘ └─────────────┘ ``` ## 3. Ansvarsfordeling | Komponent | Rolle | Snakker med | |---|---|---| -| **SvelteKit (klient)** | UI, brukerinteraksjon | Maskinrommet (HTTP), SpacetimeDB (WS) | -| **Maskinrommet (Rust)** | Intensjons-API, orkestrering, tunge spørringer | PG, SpacetimeDB, CAS, Whisper, LiteLLM | -| **SpacetimeDB** | Sanntids state, push til klienter | Klienter (WS), maskinrommet (skriver) | -| **PostgreSQL** | Persistent arkiv, søk, statistikk | Maskinrommet (SQL) | +| **SvelteKit (klient)** | UI, brukerinteraksjon | Maskinrommet (HTTP + WS) | +| **Maskinrommet (Rust)** | Intensjons-API, orkestrering, sanntid, tunge spørringer | PG, CAS, Whisper, LiteLLM | +| **PostgreSQL** | Eneste datakilde, sanntid via LISTEN/NOTIFY | Maskinrommet (SQL) | ## 4. Viktige avklaringer -- **Maskinrommet er en HTTP API-server** (axum). Frontend sender intensjoner hit. -- **Maskinrommet eier alle skrivinger.** Frontend skriver aldri direkte til PG eller STDB. -- **SpacetimeDB nås direkte** fra klienten via WebSocket for lesing (sanntid). +- **Maskinrommet er HTTP API + WebSocket-server** (axum). Frontend sender intensjoner via HTTP, mottar sanntid via WebSocket. +- **Maskinrommet eier alle skrivinger.** Frontend skriver aldri direkte til PG. - **SvelteKit er et rent frontend-prosjekt.** Ingen server-side PG-tilgang. - **Bakgrunnsjobber** (Whisper, LLM, TTS) orkestreres av maskinrommet, aldri direkte fra frontend. @@ -62,14 +59,17 @@ Tunge spørringer (søk, statistikk, graftraversering) går via maskinrommet → ### Offentlige - `GET /health` — Helsesjekk. Verifiserer PG- og STDB-tilkobling. -### WebSocket (sanntid, oppgave 22.1) +### WebSocket (sanntid, oppgave 22.1–22.2) - `GET /ws?token=` — WebSocket-oppgradering for sanntidsstrøm. Token sendes som query-parameter (nettlesere støtter ikke custom headers ved WS upgrade). - - Ved tilkobling: sender `initial_sync` med alle noder, edges og access brukeren kan se. - - Deretter: strømmer `node_changed`, `edge_changed` og `access_changed` events, - filtrert på brukerens tilgangsmatrise (node_access). - - Kilder: PG LISTEN/NOTIFY-triggere på nodes, edges og node_access-tabellene. - - Events er JSON med `{ "type": "node_changed"|"edge_changed"|"access_changed", ... }`. + - Ved tilkobling: sender `initial_sync` med alle noder, edges, access og mixer_channels + brukeren kan se. + - Deretter: strømmer berikede events (`node_changed`, `edge_changed`, `access_changed`, + `mixer_channel_changed`), filtrert på brukerens tilgangsmatrise (node_access). + - Berikede events: INSERT/UPDATE-events inneholder full raddata fra PG (ikke bare ID), + slik at frontend kan oppdatere stores direkte uten ekstra API-kall. + - Kilder: PG LISTEN/NOTIFY-triggere på nodes, edges, node_access og mixer_channels. + - Ved lag (klient sakker etter): sender full resync (ny initial_sync). ### Autentiserte (krever `Authorization: Bearer `) - `GET /me` — Returnerer autentisert brukers `node_id` og `authentik_sub`. @@ -123,10 +123,19 @@ Tunge spørringer (søk, statistikk, graftraversering) går via maskinrommet → - Body (JSON): `{ communication_id }` - Respons: `{ status: "closed" }` -### SpacetimeDB sanntidstabeller (LiveKit) -- `live_room` — Aktive rom. Felt: `room_id`, `communication_id`, `is_active`, `started_at`, `participant_count`. -- `room_participant` — Deltakere i rom. Felt: `id`, `room_id`, `user_id`, `display_name`, `role`, `joined_at`. - Frontend abonnerer på disse via SpacetimeDB WebSocket for sanntids deltakerliste. +### Mixer-kanaler (oppgave 22.2) +Erstatter SpacetimeDB-reducers for delt mixer-tilstand i LiveKit-rom. +Skriver til PG `mixer_channels`-tabell; NOTIFY-trigger propagerer til WS. +- `POST /intentions/create_mixer_channel` — Opprett mixer-kanal for deltaker i rom. + - Body: `{ room_id, target_user_id }` +- `POST /intentions/set_gain` — Sett gain (0.0–1.5) for en kanal. + - Body: `{ room_id, target_user_id, gain }` +- `POST /intentions/set_mute` — Mute/unmute en kanal. + - Body: `{ room_id, target_user_id, is_muted }` +- `POST /intentions/toggle_effect` — Toggle en lydeffekt. + - Body: `{ room_id, target_user_id, effect_name }` +- `POST /intentions/set_mixer_role` — Sett rolle (editor/viewer) for deltaker. + - Body: `{ room_id, target_user_id, role }` ## 6. Instruks for Claude Code diff --git a/docs/retninger/datalaget.md b/docs/retninger/datalaget.md index 9eb54f3..c0886cc 100644 --- a/docs/retninger/datalaget.md +++ b/docs/retninger/datalaget.md @@ -126,16 +126,18 @@ i prototype-fasen. Men for produksjon på én server: ## Migrasjonsplan: STDB → PG LISTEN/NOTIFY -### Fase M1: WebSocket-lag i portvokteren -Implementer LISTEN/NOTIFY-lytter og WebSocket-endepunkt i -portvokteren. Legg til PG-triggers for nodes og edges. -Frontend kobler til begge (STDB + nytt WS) i parallell. +### Fase M1: WebSocket-lag i portvokteren ✅ +Implementert LISTEN/NOTIFY-lytter og WebSocket-endepunkt i +portvokteren. PG-triggers for nodes, edges og access. +Frontend koblet til begge (STDB + nytt WS) i parallell. -### Fase M2: Frontend-migrering -Endre frontend fra SpacetimeDB-klient til vanlig WebSocket. -Erstatt STDB-stores med reaktive stores som lytter på -portvokterens WebSocket. Verifiser at all sanntidsfunksjonalitet -fungerer. +### Fase M2: Frontend-migrering ✅ +Frontend bruker nå kun portvokterens WebSocket. SpacetimeDB-klient +fjernet. Reactive stores oppdateres direkte fra WS-meldinger. +Berikede events: portvokteren henter full raddata fra PG etter +NOTIFY (ikke bare ID) slik at stores kan oppdateres uten ekstra +API-kall. Mixer-kanaler migrert fra STDB til PG-tabell med +tilhørende NOTIFY-trigger og HTTP API-endepunkter. ### Fase M3: Fjern skrivestien til STDB Portvokteren slutter å skrive til SpacetimeDB. All skriving diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 2daeda5..42705e5 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1281,3 +1281,70 @@ export async function fetchNodeUsage( } return res.json(); } + +// ============================================================================= +// Mixer-kanaler (oppgave 22.2 — erstatter STDB-reducers) +// ============================================================================= + +export async function createMixerChannel( + accessToken: string, + roomId: string, + targetUserId: string, +): Promise { + await post(accessToken, '/intentions/create_mixer_channel', { + room_id: roomId, + target_user_id: targetUserId, + }); +} + +export async function setMixerGain( + accessToken: string, + roomId: string, + targetUserId: string, + gain: number, +): Promise { + await post(accessToken, '/intentions/set_gain', { + room_id: roomId, + target_user_id: targetUserId, + gain, + }); +} + +export async function setMixerMute( + accessToken: string, + roomId: string, + targetUserId: string, + isMuted: boolean, +): Promise { + await post(accessToken, '/intentions/set_mute', { + room_id: roomId, + target_user_id: targetUserId, + is_muted: isMuted, + }); +} + +export async function toggleMixerEffect( + accessToken: string, + roomId: string, + targetUserId: string, + effectName: string, +): Promise { + await post(accessToken, '/intentions/toggle_effect', { + room_id: roomId, + target_user_id: targetUserId, + effect_name: effectName, + }); +} + +export async function setMixerRole( + accessToken: string, + roomId: string, + targetUserId: string, + role: string, +): Promise { + await post(accessToken, '/intentions/set_mixer_role', { + room_id: roomId, + target_user_id: targetUserId, + role, + }); +} diff --git a/frontend/src/lib/components/traits/MixerTrait.svelte b/frontend/src/lib/components/traits/MixerTrait.svelte index ff3dcb8..c1fdf1c 100644 --- a/frontend/src/lib/components/traits/MixerTrait.svelte +++ b/frontend/src/lib/components/traits/MixerTrait.svelte @@ -1,7 +1,13 @@ diff --git a/tasks.md b/tasks.md index d3dbc60..37e6310 100644 --- a/tasks.md +++ b/tasks.md @@ -280,8 +280,7 @@ til fordel for PG LISTEN/NOTIFY + WebSocket i portvokteren. Én datakilde, ingen synk-kompleksitet. - [x] 22.1 WebSocket-lag i portvokteren: implementer PG LISTEN/NOTIFY-lytter og WebSocket-endepunkt. Legg til PG-triggers (`notify_node_change`, `notify_edge_change`) for nodes og edges. Frontend kobler til begge (STDB + nytt WS) i parallell for verifisering. -- [~] 22.2 Frontend-migrering: erstatt SpacetimeDB-klient med vanlig WebSocket til portvokteren. Erstatt STDB-stores med reaktive stores som lytter på WebSocket. Verifiser all sanntidsfunksjonalitet (chat, kanban, kalender, mixer, canvas). - > Påbegynt: 2026-03-18T12:05 +- [x] 22.2 Frontend-migrering: erstatt SpacetimeDB-klient med vanlig WebSocket til portvokteren. Erstatt STDB-stores med reaktive stores som lytter på WebSocket. Verifiser all sanntidsfunksjonalitet (chat, kanban, kalender, mixer, canvas). - [ ] 22.3 Fjern STDB-skrivestien: portvokteren slutter å skrive til SpacetimeDB. All skriving går kun til PG. NOTIFY-triggere er eneste push-mekanisme. Verifiser at ingenting avhenger av STDB-data. - [ ] 22.4 Fjern SpacetimeDB: stopp Docker-container, fjern STDB-modul, fjern STDB-klient fra portvokteren og frontend, fjern synkroniseringskode, oppdater docs og CLAUDE.md. - [ ] 22.5 Opprydding: arkiver STDB-relaterte erfaringsdocs, oppdater alle docs-referanser, fjern Docker-konfig for SpacetimeDB, fjern SpacetimeDB-loven fra feedback-memories.