
# Atomicità e ripristino

`AtomicFilesystem::write_atomic()` scrive in un file temporaneo, esegue flush e
fsync sul relativo handle, lo rinomina sostituendo il percorso di destinazione e tenta di eseguire fsync
sulla directory padre. Le scritture non riuscite eliminano il proprio file temporaneo.

Le istanze di scrittura registrano un indicatore per processo in
`.storh/writers/` e lo rimuovono alla chiusura regolare. All'apertura di un archivio vengono controllati
questi indicatori: se tutti i processi proprietari sono attivi (o non ci sono indicatori), l'apertura richiede tempo costante; un indicatore il cui processo proprietario non è più attivo significa che un writer è andato in crash, quindi l'apertura esegue una scansione della raccolta per eliminare i file temporanei orfani e cancella l'indicatore obsoleto. `repair()` esegue sempre la scansione.

La riparazione di DocStore mette in quarantena i file di record corrotti o troncati in
`.storh/corrupt/` e ricostruisce gli indici secondari a partire dai record validi rimanenti. La verifica di DocStore confronta anche i file degli indici con una scansione completa dei record, così le voci mancanti o obsolete vengono segnalate prima di poter essere considerate integre.

I motori append-only eseguono flush e fsync sui rispettivi handle dei file di log prima di considerare gli eventi confermati in memoria. La durabilità in caso di interruzione di corrente dipende comunque dal fatto che il file system e le opzioni di mount rispettino le operazioni di sync sui file e sulle directory.

Il log segmentato scrive ogni riga nel formato seguente:

```text
<byte-length>\t<xxh32>\t<json>\n
```

Le letture verificano la lunghezza in byte e il checksum. Il ripristino scansiona ogni segmento e tronca il file all'ultima riga completa e valida, eliminando così le scritture finali incomplete. La verifica confronta l'indice dello stato derivato attivo con una riproduzione indipendente dei segmenti, così gli stati modificati esternamente o obsoleti vengono segnalati prima che la riparazione li ricostruisca.

La verifica della coda decodifica ogni evento persistente e confronta lo stato attuale di elementi in attesa, in elaborazione e completati, dei payload e dell'ordine di acquisizione con una riproduzione indipendente del log. La riparazione ricostruisce lo stato da `queue.log` e tronca gli eventi finali incompleti. Le acquisizioni e i completamenti mantengono il lock della coda durante la sincronizzazione dal log persistente, così più processi worker non acquisiscono lo stesso job in attesa.

La compattazione scrive nuovi file di segmento `compact-*` e poi aggiorna il manifest.
Se un processo termina prima della sostituzione del manifest, alla riapertura vengono rimossi gli output di compattazione non referenziati e si riparte dal manifest precedente. Le compattazioni completate lasciano intenzionalmente al loro posto i vecchi segmenti sigillati, così i lettori che li stanno già scorrendo continuano a usarli senza problemi.
