restate / v1.0.0
Affidabilità by design
Che cosa garantisce restate quando l’archivio è lento, fallisce o manca, e come leggere gli errori che segnala.
In questa pagina
Le garanzieSalvataggi ordinatiProvaloQuando il caricamento fallisceSalva e chiudiNessun archivio disponibileValida e migra i dati salvatiUsa il tuo archivioLimiti e timeoutCodici di erroreLe garanzie
Questi comportamenti fanno parte del contratto della 1.0 e sono coperti dai test del pacchetto.
| Situazione | Che cosa fa restate |
|---|---|
Più salvataggi di fila | Li esegue in ordine per ogni store; un salvataggio in coda scrive il valore più recente. |
Un record non si è caricato | autoSave e i salvataggi in blocco lo saltano con LOAD_FAILED; solo un save() esplicito lo sostituisce. |
Il componente viene smontato durante un salvataggio | Il salvataggio richiesto termina; le scritture successive nello store distrutto vengono ignorate. |
L’archivio non è disponibile | Lo store funziona in memoria, status().available è false, i salvataggi vengono rifiutati. |
Un adattatore si blocca | L’operazione va in timeout dopo operationTimeoutMs e il lavoro successivo aspetta che l’adattatore finisca. |
Troppo lavoro in sospeso | Le nuove operazioni vengono rifiutate con QUEUE_FULL invece di crescere senza limiti. |
Salvataggi ordinati
Le operazioni di uno store non si sovrappongono mai. Un salvataggio avviato mentre un altro aspetta prende il valore più nuovo, così salvare a ogni modifica scrive l’ultimo stato senza riempire la coda.
useDraft.set('A');
const first = useDraft.save(); // writes "A"
useDraft.set('B');
const second = useDraft.save(); // waits in the queue
useDraft.set('C');
const third = useDraft.save(); // joins the waiting save
await Promise.all([first, second, third]); // ['A', 'C', 'C'] — two writesProvalo
Rallenta l’archivio, fai fallire le scritture o rimuovi del tutto l’archivio.
Preparazione dell’esempio…
Quando il caricamento fallisce
restateManager.ready viene rifiutato con BULK_OPERATION_FAILED ed elenca ogni store fallito. Finché quel record non si carica, autoSave e saveAll non lo sostituiscono e segnalano LOAD_FAILED.
Riprova con initialize() per tenere le modifiche e salvarle, chiama restore() per scartarle o save() per sovrascrivere il record di proposito.
try {
await restateManager.ready;
} catch (error) {
// BULK_OPERATION_FAILED: one entry per store that could not load.
for (const { store, error: cause } of error.failures) {
console.error(store.key, cause.code);
}
}Salva e chiudi
Un salvataggio richiesto prima dello smontaggio termina comunque, quindi un handler «Salva e chiudi» non deve aspettare.
function Document({ onClose }) {
const useDraft = useRestateScope((scope) => persistedRestate('', { scope, key: 'draft' }));
const saveAndClose = () => {
useDraft.save(); // finishes even after this component unmounts
onClose();
};
// …
}Valida e migra i dati salvati
version, migrate e validate ti proteggono da record vecchi o corrotti. validate viene eseguito prima del salvataggio e dopo il ripristino o la migrazione.
import { persistedRestate } from '@kkwaenggwari/restate';
const useSettings = persistedRestate(
{ theme: 'system' },
{
key: 'settings',
version: 2,
migrate(value, from, to) {
if (from === 1 && to === 2 && typeof value?.darkMode === 'boolean') {
return { theme: value.darkMode ? 'dark' : 'light' };
}
throw new Error('Unsupported stored version');
},
validate: (value) => ['system', 'light', 'dark'].includes(value?.theme),
},
);Usa il tuo archivio
Va bene qualsiasi oggetto con getItem, setItem e removeItem. I metodi possono restituire valori o Promise; isAvailable è opzionale.
import { persistedRestate } from '@kkwaenggwari/restate';
const sessionStorageAdapter = {
isAvailable: () => typeof sessionStorage !== 'undefined',
getItem: (key) => sessionStorage.getItem(key),
setItem: (key, value) => sessionStorage.setItem(key, value),
removeItem: (key) => sessionStorage.removeItem(key),
};
export const useFilters = persistedRestate(
{ query: '' },
{
key: 'filters',
storage: sessionStorageAdapter,
},
);Limiti e timeout
Regola quanto può durare un’operazione, quante possono aspettare e quanto può essere grande un valore.
persistedRestate(value, {
key: 'draft',
operationTimeoutMs: 10_000, // default 30000
maxPendingOperations: 64, // default 256
maxStorageCharacters: 1_000_000,
});Codici di errore
Gli errori creati da restate hanno name RestateError, un code e, per gli store salvati, key. Gli adattatori di archiviazione e i tuoi callback possono rifiutare con errori propri.
| Codice | Significato |
|---|---|
BULK_OPERATION_FAILED | Una chiamata in blocco come restateManager.ready o saveAll ha avuto errori; vedi error.failures. |
INDEXEDDB_ABORTED | Una transazione IndexedDB è stata annullata. |
INDEXEDDB_BLOCKED | L’apertura del database è stata bloccata da una connessione in un’altra tab. |
INDEXEDDB_CONNECTION_CLOSING | La connessione al database si stava chiudendo quando è iniziata la richiesta. |
INDEXEDDB_OPEN_FAILED | Impossibile aprire il database. |
INDEXEDDB_REQUEST_FAILED | Una richiesta IndexedDB non è riuscita. |
INDEXEDDB_STORE_MISSING | L’object store non esiste in un database già creato. |
INVALID_STORAGE_RECORD | Un record salvato non è un record restate valido. |
INVALID_STORED_VALUE | Un valore non ha superato validate. |
LIFECYCLE_LIMIT | Un updater continuava ad avviarsi e fermarsi. |
LOAD_FAILED | Un record non si è potuto caricare, quindi un salvataggio automatico o in blocco non l’ha sostituito. |
MMKV_UNAVAILABLE | Impossibile caricare react-native-mmkv. |
MULTIPLE_ERRORS | Più callback sono falliti in un’operazione; vedi error.errors. |
NOTIFICATION_LIMIT | Gli osservatori continuavano a programmare modifiche in un ciclo. |
OBSERVER_ERROR | Un listener o un callback del ciclo di vita ha lanciato un errore. |
OPERATION_ABORTED | Un’operazione di archiviazione è stata annullata. |
QUEUE_FULL | In attesa c’erano più operazioni di quante ne consenta maxPendingOperations. |
REENTRANT_SETTER | Un updater di stato ha provato a cambiare lo stesso store mentre era in esecuzione. |
SCOPE_DESTROYED | È stato usato uno scope distrutto per creare store. |
SEQUENCE_EXHAUSTED | Una sequenza interna ha esaurito gli identificatori. |
STORAGE_BLOCKED | Una chiamata precedente all’adattatore non si è conclusa dopo un timeout o un annullamento. |
STORAGE_TIMEOUT | Un’operazione ha impiegato più di operationTimeoutMs. |
STORAGE_UNAVAILABLE | Qui l’archivio non può essere usato; lo store continua a funzionare in memoria. |
STORAGE_VALUE_TOO_LARGE | Il valore codificato supera maxStorageCharacters. |
STORAGE_VERSION_MISMATCH | Un record ha un’altra versione e nessuna funzione migrate la gestisce. |
STORE_DESTROYED | Ci si è iscritti a uno store distrutto o gli si è chiesto di usare l’archivio. |