Server, Datenbankrollen und Betrieb
Der Konto- und Relay-Dienst, die PostgreSQL-Rolleninvariante, die Konfiguration, die ein Entwicklungsserver braucht, und was über HTTP-Health hinaus zu prüfen ist.
Gegen den Quellcode geprüft am 5. Oktober 2026
Auf dieser Seite
Der Server besitzt Konto- und Relay-Zuständigkeiten
Die Actix-Anwendung initialisiert beim Start gemeinsame Dienste: Datenbank-Pools, Kontoauthentifizierung, Verbindungsverwaltung sowie konfigurierte Anbieter- und Push-Integrationen. Der DeviceConnectionManager wird von den HTTP-Workern des Prozesses gemeinsam genutzt. Seine Live-Sockets, Verbindungsgenerationen und ausstehenden RPC-Einträge sind Prozesszustand. Auch der Relay-Session-Speicher hinter den Resume-Tokens liegt im Arbeitsspeicher, mit einer TTL von 24 Stunden und einem Aufräumlauf alle 5 Minuten. Jeder RPC und jeder Heartbeat-Frame erneuert einen Session-Eintrag. Redis ist für den gemeinsamen Anmeldezustand, die Ratenbegrenzung und Guthabenreservierungen für bezahlte Anfragen erforderlich, und der Prozess beendet sich beim Start ohne Redis. Redis macht ein Register von Live-Sockets nicht zwischen Serverprozessen übertragbar.
Beide Geräte und ihre ausstehende Anfrage müssen diesen Connection-Manager erreichen, deshalb läuft in Produktion ein Relay-Prozess pro Region mit explizitem Verbindungsabbau. Das Kapitel zum Geräte-Routing erklärt, warum eine Round-Robin-Replik das Routing zerstören würde.
PostgreSQL-Rollen sind eine Start-Invariante
- Laufzeit-LoginsDATABASE_SYSTEM_URL · DATABASE_USER_URL
assert_runtime_boundary prüft die Principals, als die sich diese URLs verbinden, nicht die URLs. Schon vor dem Verbinden lehnt create_dual_pools zwei identische URLs ab.
- Tenant-Kontextapp.current_user_id
Mit set_config für eine Transaktion gesetzt, sodass eine Verbindung im Pool ihn am Ende der Transaktion vergisst. Zeilensicherheits-Policies, die für jedes Login geschrieben sind, entscheiden, was es anfassen darf.
- PoolsDB_POOL_SYSTEM_MAX · DB_POOL_USER_MAX
Einmal pro Serverprozess geöffnet und von allen seinen HTTP-Workern geteilt. Jeder weitere Prozess, auch die zweite Farbe während einer Blue-Green-Umschaltung, öffnet eigene.
create_dual_pools öffnet beide Pools und führt assert_runtime_boundary für die Principals aus, als die sie tatsächlich verbunden sind, sodass eine URL mit der falschen Rolle an denselben Prüfungen scheitert.
| Standardwert | System-Pool | Tenant-Pool |
|---|---|---|
| Maximale Verbindungen | 8 | 16 |
| Minimale Verbindungen | 2 | 4 |
| application_ | hbcode-system | hbcode-user |
| Statement-Timeout | 30 Sekunden | 8 Sekunden |
| Idle-in-Transaction-Timeout | 60 Sekunden | 10 Sekunden |
| Lock-Timeout | 5 Sekunden | 2 Sekunden |
Beide Pools nutzen 2 Sekunden Acquire-Timeout, 60 Sekunden Leerlauf-Timeout und eine maximale Verbindungslebensdauer von 1.800 Sekunden. Jede Verbindung setzt die Zeitzone auf UTC. Ein fehlgeschlagener Verbindungsaufbau wird bis zu fünfmal versucht, und die Wartezeit wächst mit jedem Versuch um eine Sekunde. Jeder Serverprozess öffnet eigene Pools, die seine HTTP-Worker teilen. Weitere Prozesse, auch die zweite Farbe einer Blue-Green-Umschaltung, vervielfachen die Verbindungen und brauchen zuerst eine Prüfung der Datenbankkapazität.
Lokalen Server konfigurieren
- Kopieren Sie server/.env.example nach server/.env und konfigurieren Sie eine lokale Datenbank, eine Redis-URL, Einstellungen zur Verschlüsselung von JWT- und Refresh-Tokens sowie Auth0-Werte.
- Legen Sie getrennte Migrations- und Runtime-Principals gegen eine lokale Entwicklungsdatenbank an.
- Wenden Sie server/scripts/run-migrations.sh mit der benötigten Migrationsumgebung an. server/README.md beschreibt die Rollenbereitstellung und die Erhaltungsrichtlinie.
cp server/.env.example server/.env
# Configure the local services and database roles first.
pnpm server:check
pnpm dev:serverDer Migrations-Runner verarbeitet infrastructure/ansible/playbooks/plantocode/migration-execution-plan.yml, denselben geordneten Plan, den die Bereitstellung nutzt. Die Migrationsrolle muss ein Superuser sein, der keiner von postgres, hbcode oder authenticated ist und in DATABASE_RUNTIME_ROLES fehlt. Als execution once markierte Dateien werden per sha256 in plantocode_internal.migration_execution_ledger gesperrt, und der Runner bricht ab, wenn eine Laufzeitrolle dieses Ledger erreichen kann. Eine Prüfsummenabweichung, eine once-Datei ohne einzelne Transaktion oder eine ungeplante .sql-Datei bricht die Ausführung ab. PRESERVE_EXISTING_DATABASE_IDENTITIES=true wird nur für die expand-Phase akzeptiert. Ersetzen Sie den Runner nicht durch sqlx migrate run.
| Zweck | Einstellungen und wann sie erforderlich sind |
|---|---|
| Kerndienste | DATABASE_ |
| Konto-Anmeldung | AUTH0_ |
| Tokens | JWT_ |
| Anbieter | Provider-API-Schlüssel. Nur die entsprechenden konfigurierten Provider-Routen. |
| Integrationen | Stripe-, APNs-, FCM-, E-Mail- und weitere Integrationseinstellungen. Ihre jeweiligen Konto- oder Benachrichtigungsfunktionen. |
| Weitere Datenbanken | METRICS_ |
| Service-Health | SERVICE_ |
| Vorschauen | WORKSPACE_ |
| Deployment | PLANTOCODE_ |
Verhalten jenseits des HTTP-Health-Checks verifizieren
GET /health prüft den grundlegenden Serverzustand. Das geschützte /health/deployment unterstützt die Deployment-Inspektion. Verifizieren Sie anschließend einen Konto-Login, zwei Geräteregistrierungen, einen schreibgeschützten Desktop-RPC und eine kontrollierte Outbox-Operation. Ein fehlerfreier HTTP-Listener allein testet weder die Trennung von Datenbankrollen noch native Callbacks, Provider-Konfigurationen oder das Relay-Routing.
Eine nützliche Relay-Spur folgt der Anfrage-ID, dem Quell-Client, dem Ziel-Desktop, der Methode und der Verbindungsgeneration. Der Weiterleitungscode extrahiert den W3C-Trace-Kontext und injiziert den Kindkontext in den nächsten Hop. Bei mehrdeutiger Zustellung prüfen Sie den remote_rpc_idempotency-Anspruch des Desktops und seine chat_operation_ledger-Zeilen, bevor Sie schließen, ob Arbeit gelaufen ist.
- Backup/usr/local/bin/backup_postgresql.sh
Läuft auf jedem Host zuerst. Seine geprüfte Ausgabe ist der einzige Weg zurück nach einer Vorwärtsmigration.
- Expandsite-app.yml --tags api-expand
Wendet den abwärtskompatiblen Teil des Migrationsplans an. Die Binärdatei, die noch läuft, arbeitet auf dem erweiterten Schema weiter.
- Binärdatei und Soak-Phasesite-app.yml --tags api-binary-deploy
Aktiviert die neue Binärdatei mit den Blue-Green-Diensten. Der Betreiber prüft Health und Logs und wartet das Ende der Soak-Phase ab.
- Migratesite-app.yml --tags api-migrate
Schreibt beide Release-Farben fest und wendet den Contract-Teil des Plans an. Nach diesem Schritt gibt es keine allgemeine Rollback-Aktion.
- Ein Host pro Lauf--limit interserver-us · --limit hetzner-primary
Jede Aktion, die die Produktion ändert, zielt auf genau einen Host im Inventar. Die EU-Abfolge beginnt erst, wenn das Canary-Ergebnis geprüft ist.
Die Produktion hat zwei Hosts im Ansible-Inventar: interserver-us in den USA und hetzner-primary in der EU. Jeder betreibt den Server als zwei Dienste, plantocode-blue auf Port 8080 und plantocode-green auf Port 8081. Jede Aktion, die die Produktion ändert, läuft über site-app.yml mit genau einem Host in --limit. infrastructure/ansible/operations.md ist das Runbook. Inventar und Geheimnisse sind Betreiberkonfiguration.
| Schritt auf einem Host | Aktion und Ergebnis |
|---|---|
| Backup | backup_ |
| Expand | --tags api-expand. Die abwärtskompatible Phase des Migrationsplans ist angewendet und bestätigt. |
| Binary | --tags api-binary-deploy. Die neue Binärdatei ist aktiv. Der Betreiber prüft Health und Logs und schließt die Soak-Phase ab. |
| Migrate | --tags api-migrate. Beide Release-Farben sind festgeschrieben, und die Contract-Phase ist angewendet. |
Das Runbook verbietet drei Abkürzungen. Kopieren Sie nie eine Release-SQL-Datei auf einen Server, um psql von Hand auszuführen. Führen Sie nie eine Anwendungs- oder Datenbankänderung ohne genau ein --limit aus. FLUSHALL in Redis ist keine routinemäßige Wiederherstellung und braucht die ausdrückliche Freigabe des Betreibers.