---
title: "Aggiornare senza tempi di fermo"
description: "Aggiorna un Quire autonomo senza tempi di fermo."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/it/llms.txt
> Use this file to discover all available pages before exploring further.

# Aggiornare senza tempi di fermo

<span id="upgrading-without-downtime"></span>

Le regole sono nella sezione 7 di `docs/architecture/23-ops.md` e nella
sezione 4.1 di `docs/architecture/07-data.md`. Questa è la procedura.

## La garanzia che rende tutto sicuro <!--quire:the-guarantee-that-makes-it-safe-->

**La release R funziona correttamente con lo schema R e lo schema R meno uno.** Ogni
modifica di schema è divisa in espansione, transizione e consolidamento:

1. **Espansione**: aggiungi la nuova colonna, tabella o indice. Il vecchio codice la ignora.
2. **Transizione**, per almeno una release: il nuovo codice scrive in entrambe le forme e
   legge quella nuova; un job ripristinabile riempie le vecchie righe.
3. **Consolidamento**: elimina la vecchia forma, in una release successiva, da sola.

Così in ogni momento di un aggiornamento progressivo, processi vecchi e nuovi possono condividere un unico
database. Non esistono migrazioni a ritroso: una migrazione che ha eliminato una colonna un'ora
fa non può restituire le righe scritte in quell'ora.

Il job CI `schema-compat` verifica la garanzia a ogni release eseguendo
i test della release precedente contro il nuovo schema.

## Prima di iniziare <!--quire:before-you-start-->

1. Leggi le note di release. Una release che richiede una finestra di manutenzione lo dice,
   con la stima; al massimo una per release.
2. Esegui la prova di ripristino, oppure verifica che sia risultata verde per questa release
   ([backup-restore.md](/it/ops/backup-restore/)). Una prova fallita blocca
   l'aggiornamento.
3. Fai un backup di base: `docker compose -f docker/compose.yaml --profile backup
   run --rm backup`.

## Docker Compose, un solo host <!--quire:docker-compose-one-host-->

```sh
export QUIRE_RELEASE=2026.10.0            # or set it in docker/.env
docker compose -f docker/compose.yaml pull   # or build
docker compose -f docker/compose.yaml run --rm migrate
docker compose -f docker/compose.yaml up -d --no-deps web content collab
docker compose -f docker/compose.yaml up -d --no-deps worker scheduler
```

L'ordine è intenzionale:

1. **Prima la migrazione**, mentre la vecchia release serve traffico. Le migrazioni di espansione
   sono invisibili per lei.
2. **Poi il livello web.** A SIGTERM ciascun processo web commuta `/readyz` su
   `draining`, completa le richieste in corso entro 30 secondi, chiude gli stream
   con un suggerimento di riconnessione ed esce. `stop_grace_period` è 40 secondi così
   Compose non interrompe mai un drenaggio sano.
3. **Per ultimi i worker**, così la forma evento più recente viene prodotta prima che il consumatore più
   recente la richieda. I worker smettono subito di prelevare e hanno 120 secondi;
   un job che non riesce a finire viene prelevato altrove, il che è sicuro perché
   ogni job è idempotente. Lo scheduler cede la leadership al suo prossimo
   tick.

Su un solo host, Compose sostituisce ciascun contenitore a turno, quindi c'è una breve pausa
per servizio. Per non avere alcuna pausa, esegui il livello web come due contenitori dietro
il tuo proxy (un file di override che aggiunge un secondo servizio web senza
porta pubblicata), e ricreali uno alla volta, attendendo che ciascuno risulti
sano prima del successivo.

## Più host o un orchestratore <!--quire:several-hosts-or-an-orchestrator-->

Usa lo stesso ordine: migra una volta da un singolo job, poi fai rolling del livello web
con picco uno e non disponibili zero, poi i worker. Punta le sonde di readiness
a `/readyz` e quelle di liveness a `/healthz`.

Con database tenant dedicati, il passaggio `migrate` fa entrambe le cose: migra
prima il database di controllo, poi ogni database elencato in
`ops.tenant_database`, uno alla volta, ciascuno sotto il proprio lock. Un fallimento in
un database tenant non ferma gli altri. Quando ogni database ha finito,
confronta i registri delle migrazioni ed esce non-zero a meno che ogni database abbia
applicato esattamente le migrazioni del database di controllo, nominando ciascuno
in ritardo o in avanti. Lo stesso comando installa le tabelle di coda in ciascun
database, perché il worker consuma i job di un tenant fissato dove sono stati
scritti.

```sh
bun apps/worker/src/migrate.ts   # what the Compose step runs
bun run db:migrate:all                            # the same, from a checkout
```
La migrazione normale e la configurazione iniziale installano anche i documenti legali inglesi canonici dell'operatore Quire in `ops.platform_policy_version`. Il programma di installazione è idempotente: vengono sostituiti solo i testi inglesi mancanti ed esattamente i testi segnaposto creati dalla migrazione. I seed vengono archiviati e viene inserita una nuova versione pubblicata; i riferimenti storici di accettazione e i testi vengono conservati. Qualsiasi versione autentica scritta dall'operatore, bozza inclusa, viene conservata e deve essere gestita tramite la console Policy della piattaforma. Documenti, versioni e consenso delle policy dei tenant non vengono mai modificati da questo cutover. Si tratta della pubblicazione del testo dell'operatore, non di una certificazione legale né dell'adempimento automatico delle sue promesse.


Ciascun database dedicato è raggiunto tramite il nome con cui è registrato.
Un database registrato come `env:QUIRE_DB_NORTHWIND_URL` richiede:

| Variabile | Usata per |
| --- | --- |
| `QUIRE_DB_NORTHWIND_URL` | Il ruolo applicativo, per il livello web e il worker |
| `QUIRE_DB_NORTHWIND_URL_MIGRATOR` | Il ruolo migratore, per questo comando e per gli spostamenti |
| `QUIRE_DB_NORTHWIND_URL_SUPERUSER` | Facoltativo: riapplica il bootstrap (ruoli, schemi, helper) prima di migrare |

Un database registrato senza connessione `_MIGRATOR` viene segnalato come fallimento,
mai saltato. Il livello web può procedere col rolling una volta finito il database di controllo. Un
database tenant indietro di un'ora avvisa; di un giorno chiama.

## pgvector <!--quire:pgvector-->

Dalla migrazione 0264 il corpus di grounding usa un indice HNSW pgvector dove
il server ha l'estensione; il servizio `postgres` di Compose è compilato con essa
(`docker/postgres.Dockerfile`). Il primo `migrate` dopo il cambio
di immagini crea l'estensione tramite il bootstrap superuser, e la 0264 poi
aggiunge una colonna vettoriale generata e costruisce l'indice. Aggiungere la colonna
riscrive `app.ai_chunk` una volta sotto lock esclusivo, quindi le richieste di grounding
attendono; nient'altro tocca quella tabella.

Su un server senza pgvector, la 0264 registra un avviso e non cambia nulla, e
il recupero resta esatto. Con un pgvector precedente alla 0.8 la colonna e l'indice
vengono costruiti ma il recupero resta esatto finché l'estensione non viene aggiornata
(`alter extension vector update`), perché le scansioni HNSW filtrate richiedono le scansioni
iterative della 0.8. Per abilitarlo in seguito su un server che ne è privo, installa
l'estensione, esegui di nuovo il bootstrap (oppure `create extension vector` come
superuser), poi come `quire_migrator`:

```sql
set maintenance_work_mem = '1GB';  -- the HNSW build is much faster in memory
select ops.ai_chunk_enable_vector_index();
```

È idempotente e restituisce `enabled` oppure `unavailable`. Eseguilo anche su ciascun
database tenant dedicato.

## Rollback <!--quire:rolling-back-->

Il rollback del **codice** è sempre disponibile: imposta `QUIRE_RELEASE` al
tag precedente e di nuovo `up -d`. Funziona perché lo schema è compatibile
in entrambe le direzioni all'interno di una release.

Il rollback dello **schema** non è offerto. Ciò che non può essere annullato, e come
recuperare:

| Non reversibile | Recupero |
| --- | --- |
| Una migrazione di consolidamento che ha eliminato una colonna | Ripristino point-in-time a prima dell'eliminazione in un nuovo database, estrazione, fusione |
| Una modifica dati sul posto | Come sopra, poi riconcilia le scritture successive |
| Webhook ed eventi inviati | Eventi compensativi, mai eliminazione |
| Email inviate | Una persona scrive il follow-up |
| La catena hash di audit | Mai riscritta; accoda una voce di correzione |

Per questo una migrazione di consolidamento viaggia da sola: un ripristino ha così un confine
pulito.

## Verifica dell'aggiornamento <!--quire:checking-the-upgrade-->

```sh
docker compose -f docker/compose.yaml ps           # every service healthy
curl -fsS http://localhost:8080/readyz             # ready, and what is configured
docker compose -f docker/compose.yaml logs migrate # the migrations applied
```

Source: https://docs.quirelms.com/it/ops/upgrade/index.mdx
