Dokumenter SpacetimeDB-loven: aldri PG-lekkasje i frontend/workers
CLAUDE.md: Ny seksjon med fire eksplisitte regler for data som frontend viser. synkronisering.md: §9 Workers som endrer synlig data — riktig vs feil flyt. adapter_moenster.md: §5 Anti-pattern enrichFromPg — gjentatt 3+ ganger. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c5bd0c0130
commit
1e065b827d
3 changed files with 85 additions and 4 deletions
|
|
@ -82,3 +82,11 @@ CLAUDE.md er eneste startdokument. Alt annet ligger under `docs/`:
|
|||
- Sjekk alltid relevant doc i `docs/concepts/`, `docs/features/` eller `docs/infra/` før du implementerer
|
||||
- Sjekk `docs/erfaringer/` for kjente feller før du implementerer med Svelte 5, SpacetimeDB eller adapter-mønsteret
|
||||
- Etter ferdig implementering av en komponent: dokumenter lærdommer i `docs/erfaringer/`
|
||||
|
||||
## SpacetimeDB-loven (les `docs/infra/synkronisering.md` for detaljer)
|
||||
SpacetimeDB er autoritativ sanntidskilde for data som frontend leser. **All kode** — frontend-adaptere, workers, bakgrunnsjobber — følger disse reglene:
|
||||
|
||||
1. **Frontend → SpacetimeDB.** Aldri direkte PG-kall for data som SpacetimeDB eier (chat, kanban, markører). Ingen `enrichFromPg`, ingen PG-polling, ingen metadata-hacks.
|
||||
2. **Worker → SpacetimeDB → PG.** En worker som endrer data frontend ser (f.eks. AI-vask av meldinger) skriver resultatet til SpacetimeDB via reducer. Sync-workeren persisterer til PG i bakgrunnen. Worker leser fra PG (jobbkø, prompts), men skriver synlig resultat til SpacetimeDB.
|
||||
3. **Nytt felt = utvid SpacetimeDB-modulen.** Trenger frontend `metadata`, `edited_at` eller `revisjoner`? Legg det til i SpacetimeDB-modulen, ikke hack rundt med PG API-kall fra frontend.
|
||||
4. **PG er backup, ikke snarvei.** PG-adaptere er fallback for miljøer uten SpacetimeDB. De er ikke en "enklere vei" for nye features.
|
||||
|
|
|
|||
|
|
@ -55,7 +55,28 @@ SpacetimeDB er en varm cache foran PostgreSQL:
|
|||
- Konsistent datamodell — alt kommer fra én kilde
|
||||
- Reaksjoner håndteres via SpacetimeDB-tabeller, ikke PG API
|
||||
|
||||
## 5. Anbefaling for neste komponent
|
||||
## 5. Historisk anti-pattern: "PG-lekkasje" i SpacetimeDB-adapteren
|
||||
|
||||
Gjentatt feil (mars 2026, minst 3 iterasjoner): Når en ny feature trenger data som SpacetimeDB-modulen ikke har (metadata, edited_at, revisjoner), er det fristende å legge til en `enrichFromPg()`-funksjon som henter fra PG direkte. Dette bryter hele poenget med caching-laget.
|
||||
|
||||
**Symptomer:**
|
||||
- SpacetimeDB-adapteren har `fetch('/api/messages/...')` kall
|
||||
- Worker skriver til PG først, SpacetimeDB er "best-effort"
|
||||
- Etter AI-vask vises ikke metadata/revisjoner fordi de bare finnes i PG
|
||||
- Race conditions mellom SpacetimeDB-oppdateringer og PG-fetch
|
||||
|
||||
**Hvorfor det skjer:** Det er raskere å lage en PG API-rute enn å utvide SpacetimeDB-modulen (Rust compile, publish, regenerer bindings). Men det skaper teknisk gjeld som akkumulerer og undergraver hele arkitekturen.
|
||||
|
||||
**Riktig løsning når SpacetimeDB mangler et felt:**
|
||||
1. Legg til feltet i SpacetimeDB Rust-modul (`spacetimedb/src/lib.rs`)
|
||||
2. Utvid warmup til å laste feltet fra PG
|
||||
3. Utvid sync til å persistere feltet til PG
|
||||
4. Worker skriver til SpacetimeDB via reducer
|
||||
5. Frontend leser kun fra SpacetimeDB
|
||||
|
||||
**Aldri:** Legg til `fetch('/api/.../metadata')` i SpacetimeDB-adapteren.
|
||||
|
||||
## 6. Anbefaling for neste komponent
|
||||
|
||||
Når Kanban eller Whiteboard skal bygges med SpacetimeDB:
|
||||
|
||||
|
|
@ -64,3 +85,4 @@ Når Kanban eller Whiteboard skal bygges med SpacetimeDB:
|
|||
3. **Bruk samme factory-mønster.** Felles interface, env-variabel for valg.
|
||||
4. **Legg til warmup-config** i `channels.config` (eller tilsvarende config-felt).
|
||||
5. **Test begge adaptere uavhengig** før du integrerer i UI-komponenten.
|
||||
6. **Sjekk at alle felter frontend trenger finnes i SpacetimeDB-modulen** før du implementerer adapteren. Utvid modulen først hvis nødvendig.
|
||||
|
|
|
|||
|
|
@ -101,7 +101,52 @@ Kanban-kort har en `position`-kolonne (float). To brukere som drar kort samtidig
|
|||
### 8.3 Chat: Ingen konflikter
|
||||
Meldinger er append-only. Redigering av egne meldinger er last-write-wins — akseptabelt fordi kun én bruker eier meldingen.
|
||||
|
||||
## 9. Implementeringsstatus (mars 2026)
|
||||
## 9. Workers som endrer data frontend ser
|
||||
|
||||
**Kritisk regel:** En worker (Rust) som transformerer data som frontend viser, MÅ skrive resultatet til SpacetimeDB — ikke direkte til PG. PG-oppdatering skjer via sync-worker i bakgrunnen.
|
||||
|
||||
### Eksempel: AI-vask av chatmelding
|
||||
|
||||
**Riktig flyt:**
|
||||
```
|
||||
Frontend viser melding fra SpacetimeDB
|
||||
→ Bruker trykker ✨
|
||||
→ SvelteKit oppretter jobb i PG job_queue
|
||||
→ Worker plukker opp jobb
|
||||
→ Worker leser prompt + routing fra PG (det er infrastrukturdata, ikke frontend-data)
|
||||
→ Worker kaller AI Gateway
|
||||
→ Worker skriver resultat til SpacetimeDB via edit_message reducer
|
||||
→ SpacetimeDB pusher oppdatering til frontend via onUpdate
|
||||
→ Sync-worker persisterer til PG i bakgrunnen
|
||||
```
|
||||
|
||||
**Feil flyt (anti-pattern som har blitt implementert gjentatte ganger):**
|
||||
```
|
||||
Worker skriver til PG direkte
|
||||
→ Frontend henter metadata fra PG via enrichFromPg() ← BRYTER ABSTRAKSJONEN
|
||||
→ SpacetimeDB-oppdatering er "best-effort" ← FEIL PRIORITERING
|
||||
```
|
||||
|
||||
### Hva betyr dette for nye felter?
|
||||
|
||||
Når frontend trenger å vise noe nytt (metadata, revisjoner, edited_at), er prosedyren:
|
||||
|
||||
1. **Utvid SpacetimeDB-modulen** — legg til feltet i Rust-strukturen
|
||||
2. **Utvid warmup** — last feltet fra PG ved oppstart
|
||||
3. **Utvid sync** — persist feltet til PG i bakgrunnen
|
||||
4. **Worker skriver til SpacetimeDB** — via reducer, aldri direkte PG for synlig data
|
||||
5. **Frontend leser fra SpacetimeDB** — ingen enrichFromPg, ingen PG API-kall
|
||||
|
||||
### Hva kan workers lese fra PG?
|
||||
|
||||
Workers kan og bør lese infrastrukturdata direkte fra PG:
|
||||
- Jobbkø (`job_queue`) — det er jobbens opphavssted
|
||||
- AI-prompts, modellkonfigurasjon, routing — det er infrastruktur, ikke brukerdata
|
||||
- Workspace-konfigurasjon
|
||||
|
||||
Skillet er: **data frontend viser** → SpacetimeDB. **Data kun worker trenger** → PG direkte.
|
||||
|
||||
## 10. Implementeringsstatus (mars 2026)
|
||||
|
||||
### Ferdig
|
||||
- **SpacetimeDB som cache foran PG:** PG er autoritativ, SpacetimeDB er varm cache. Frontend snakker kun med SpacetimeDB.
|
||||
|
|
@ -112,12 +157,18 @@ Meldinger er append-only. Redigering av egne meldinger er last-write-wins — ak
|
|||
- **PG-fallback** (`web/src/lib/chat/pg.svelte.ts`): Brukes kun når SpacetimeDB ikke er konfigurert. Markert som `readonly: true`.
|
||||
- **Adapter-mønster:** `ChatConnection`-interface med `send`, `edit`, `delete`, `react` metoder. Factory velger basert på env-variabel.
|
||||
|
||||
### Gjenstår
|
||||
### Gjenstår — brudd på SpacetimeDB-loven som må fikses
|
||||
- **`enrichFromPg` i spacetime-adapteren** — frontend leser metadata/edited_at fra PG fordi SpacetimeDB-modulen mangler disse feltene. MÅ fjernes ved å utvide SpacetimeDB-modulen.
|
||||
- **Worker AI-vask skriver til PG direkte** — metadata, body og revisjoner skrives til PG. MÅ endres til å skrive til SpacetimeDB via reducers.
|
||||
- **Revisjoner kun i PG** — `message_revisions`-tabell finnes kun i PG. MÅ speiles i SpacetimeDB-modulen.
|
||||
- **`ChatMessage` mangler felter** — `metadata` (jsonb), `edited_at` (timestamp) mangler i SpacetimeDB-modulen.
|
||||
|
||||
### Gjenstår — andre
|
||||
- **Workspace-partisjonering (§7):** SpacetimeDB-modulen har `workspace_id`-felt men bruker ikke workspace-token på tilkobling ennå.
|
||||
- **Pin/konvertering via SpacetimeDB:** Pin og kanban/kalender-konvertering går fortsatt direkte til PG API.
|
||||
- **Lazy warmup per kanal:** Alle aktive kanaler oppvarmes ved oppstart. Kan optimaliseres til per-kanal ved tilkobling.
|
||||
|
||||
## 10. Instruks for Claude Code
|
||||
## 11. Instruks for Claude Code
|
||||
- `sync_outbox`-tabellen i SpacetimeDB bør ha et `synced`-flagg og `created_at`-tidsstempel
|
||||
- Workeren skal bruke jobbkø-infrastrukturen (se `docs/infra/jobbkø.md`) for sin egen helse/observabilitet, men selve pollingen er en egen loop — ikke en vanlig jobb i køen
|
||||
- Hold sync-payloaden enkel: `{ "table": "chat_messages", "action": "insert", "data": {...} }` — workeren mapper dette til riktig PG-tabell
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue