08 - Schema e componenti SQL
Il runtime modifica i dati; il migratore modifica la struttura. La base iniziale mantiene questa separazione. Il supporto per ulteriori componenti scriventi dello stesso sistema richiede un'estensione della nostra delivery, non un nuovo database né più privilegi al backend.
Qui parliamo di componenti che dipendono dalle stesse tabelle o dallo stesso schema applicativo. Condividere soltanto l'istanza Cloud SQL, come Access e Farm, non crea questa dipendenza.
Chi è responsabile di cosa¶
| Parte | Responsabilità |
|---|---|
| Infrastruttura | Istanza/database, rete, identità, baseline dei ruoli e permessi. Terraform e la procedura SQL preparano l'accesso. |
| Sistema applicativo, per esempio Access | Modello dati, schema e migrazioni versionate, compatibilità delle proprie versioni. Possono restare nella stessa repository del codice. |
| Job migratore | Esegue le migrazioni approvate con identità distinta, registra quelle applicate e usa il lock previsto per evitare esecuzioni concorrenti incompatibili. |
| Backend, consumer e altri runtime | Leggono e modificano soltanto i dati autorizzati, ciascuno con il proprio ruolo SQL. Non creano/modificano tabelle, non assumono il ruolo del migratore e non eseguono migrazioni all'avvio. Se scrivono nel database controllano la versione dello schema all'avvio. |
Ruoli SQL e controllo dello schema (11 novembre)¶
- Un ruolo SQL per componente. Relay, consumer, sweeper,
bootstrap-admine Dev ORM hanno ognuno il proprio ruolo, con i soli grant che servono, non il<system>_runtimecondiviso; il backend ha il suo e solo il migratore ha il ruolo owner. I nomi dei ruoli si fissano insieme prima di scrivere i baseline, e il baseline unico di ogni sistema contiene i grant completi dei ruoli concordati. - Controllo dello schema all'avvio. Ogni runtime che scrive nel database dichiara di cosa ha bisogno (tabelle, colonne, privilegi del proprio ruolo, sequenze) e lo verifica nel catalogo del database prima di servire o prendere lavoro, con
SchemaRequirementdimoonitoring-common-rs. Un bisogno non soddisfatto ferma il processo; uno schema più avanti che aggiunge soltanto viene accettato. Dettagli in Application Delivery. - Nessun DDL fuori dal migratore. Tabelle, indici, ruoli e grant cambiano solo nelle migrazioni del sistema, eseguite dal Job migratore.
Eccezione datata: baseline unico e reset dello stage (11 novembre)¶
Prima del primo rilascio reale in stage, e una sola volta, ogni sistema riunisce le sue migrazioni in un unico baseline e il suo database di stage viene svuotato. È l'unica eccezione alla regola "una migrazione applicata non si modifica" (Releases and Versioning, 4.11.4). Vale solo per lo stage, che contiene dati sintetici; in prod non esiste.
| Chi | Che cosa |
|---|---|
| Sistema (Lorenzo) | Il baseline unico, cioè la prima e unica migrazione del sistema, e in stage_grants.sql i GRANT di ogni ruolo di componente sulle sole tabelle che usa. Nessun codice distruttivo nel migratore o nei runtime. |
| Infra (Jacopo) | Il runbook di reset approvato da infra-admins e il runner tools/sql-stage-check di moonitoring-infra, eseguito con l'identità del migratore del sistema; poi il baseline SQL v3 con i ruoli <sistema>_<componente> e la loro ricevuta. |
| Pipeline | Il primo rilascio approvato esegue il migratore sullo schema vuoto, poi il backend e gli altri componenti nell'ordine concordato. |
Il reset segue sempre questi passi:
- backup on-demand dell'istanza;
- inventario in sola lettura degli oggetti di
<sistema>_ownernello schemapublic, con un hash che l'operatore approva; - esecuzione solo con quell'hash: drop di quegli oggetti con
RESTRICT. MaiDROP OWNED BY, maiCASCADE, mai cancellare o ricreare il database; - baseline SQL v3 e verifica dei ruoli;
- primo rilascio dalla pipeline.
Finché runbook e runner non sono uniti in moonitoring-infra e il reset di un sistema non è stato eseguito, il suo database di stage conserva la storia attuale. Dopo il reset tornano a valere senza eccezioni le regole di compatibilità di questa scheda.
Per ogni schema del sistema serve una responsabilità e una sequenza coerente di migrazioni. Non un migratore globale per Access, Farm e tutti gli altri database, né migratori concorrenti con evoluzioni indipendenti dello stesso schema. La separazione dei privilegi non richiede una repository diversa o interventi manuali dalla console. In PostgreSQL l'ownership consente modifiche strutturali: non va assegnata ai runtime. Privilegi PostgreSQL.
In quale senso il database guida il rilascio¶
Lo schema disponibile vincola quali versioni possiamo attivare. Modello dati e software vengono progettati insieme; le esigenze del prodotto possono richiedere nuove strutture. Il backend non decide autonomamente di trasformare il database quando parte.
Esempio: aggiungere una colonna opzionale, senza cambiare il comportamento atteso dal vecchio codice.
- Una migrazione versionata prepara la colonna e i permessi necessari, restando compatibile con i componenti in esecuzione.
- Dopo il successo si rilasciano i componenti che la usano, anche in momenti diversi.
- Eventuali rimozioni di vecchie strutture arrivano soltanto quando nessun componente attivo o previsto per il recupero ne dipende più; si verificano anche i dati da conservare.
Quindi “prima tutto il database, poi tutto il codice” non è una regola universale. Le aggiunte compatibili possono precedere il codice; le rimozioni incompatibili lo seguono. Una patch che usa lo schema esistente non richiede una modifica SQL. Le transazioni e l'idempotenza delle normali scritture rimangono responsabilità applicative: il lock delle migrazioni non le risolve.
Cosa serve ora per chiudere la base comune¶
Il percorso collaudato Access/Farm è migratore separato → successo → nuovo backend. Il Job applica solo le migrazioni mancanti; se non ce ne sono termina senza applicarne. Un errore ferma il nuovo backend, non implica lo spegnimento di quello già in esecuzione. Cloud Deploy fornisce il passaggio predeploy, mentre la nostra procedura avvia e verifica il Job.
Per la consegna iniziale completiamo procedura operatore, test dei privilegi e recupero di questo percorso, insieme agli altri punti del piano. Un nuovo sistema con un backend e un migratore può riusarlo dopo la propria registrazione e verifica. Non occorre prima abilitare tutti i consumer o worker futuri.
Già nella versione iniziale si possono preparare due release dello stesso backend: l'ordine di approvazione e recupero va quindi provato ora, come specificato in 02 e 06. Access verifica immagine/identità del Job, usa l'etag all'avvio e un lock SQL durante la migrazione; queste protezioni non certificano l'ordine dell'intero rollout. Nella v1 si torna al comportamento precedente con una fix/revert su main, conservando le migrazioni applicate e verificando lo schema corrente; non si riusa una vecchia release Cloud Deploy. Non si presume una cancellazione delle modifiche SQL già riuscite.
Database più avanti del codice¶
SeaORM possiede già il controllo delle versioni applicate: se il ledger contiene una migrazione che il codice del migratore non conosce, l'esecuzione si ferma. I test espliciti verificano che il Job fallisca e il nuovo backend non parta, senza riscrivere la storia del database. Non è una nuova funzione da affidare al backend o un confronto con il solo numero massimo di versione.
Una fix/revert valida conserva tutte le migrazioni già applicate e modifica solo
il comportamento compatibile. Non rimuovere file o registrazioni per far passare
il controllo. I test nuovi riguardano il codice della repository, non un deploy:
Farm online resta al commit fc5d06e con le due migrazioni del collaudo; i successivi
commit di sviluppo contengono altre migrazioni e non sono stati distribuiti da
queste prove. Versioni a cui si riferiscono i risultati.
Un secondo runtime scrivente¶
PostgreSQL supporta più scrittori, e dall'11 novembre li supporta anche la nostra delivery con i profili service-runtime-sql e job-runtime-sql:
- una delivery per componente, con identità e ruolo SQL propri (
<sistema>_<componente>), scrittura limitata alle tabelle concesse instage_grants.sql, senza DDL né migratore indipendente; - il prerequisito di schema verificato all'avvio dal componente stesso, nel catalogo del database (sopra);
- ordine ed esiti tracciati: il migratore del sistema gira con il backend, i componenti dipendenti si rilasciano dopo, ognuno con le proprie immagini ed esito;
- collaudo di permessi, prerequisiti, fallimenti e recupero (06), con i primi rilasci reali dopo il reset dello stage. Fino ad allora i profili sono implementati ma non collaudati dal vivo.
I rilasci non sono atomici tra componenti e non richiedono sempre lo stesso commit. Una patch compatibile può aggiornare solo il consumer. Se la migrazione fallisce, i rilasci dipendenti restano bloccati; se fallisce un consumer dopo una migrazione riuscita, si recupera quel componente senza presumere di annullare lo schema. L'estensione deve essere accettata prima dell'uso ordinario del componente aggiuntivo, non prima di ogni futuro servizio.