restate / v1.0.0

Betrouwbaarheid by design

Wat restate garandeert als opslag traag is, faalt of ontbreekt, en hoe je de gemelde fouten leest.

Op deze paginaDe garantiesSaves op volgordeProbeer hetAls laden misluktOpslaan en sluitenGeen opslag beschikbaarOpgeslagen data valideren en migrerenJe eigen opslag gebruikenLimieten en time-outsFoutcodes

De garanties

Dit gedrag hoort bij het contract van 1.0 en wordt gedekt door de tests van het pakket.

SituatieWat restate doet
Meerdere saves achter elkaarVoert ze per store op volgorde uit; een save in de wachtrij schrijft de nieuwste waarde.
Een record laadde nietautoSave en bulksaves slaan het over met LOAD_FAILED; alleen een expliciete save() vervangt het.
Het component unmount tijdens een saveDe aangevraagde save wordt afgemaakt; latere schrijfacties naar de vernietigde store worden genegeerd.
Opslag is niet beschikbaarDe store werkt in het geheugen, status().available is false en saves worden geweigerd.
Een adapter loopt vastDe bewerking verloopt na operationTimeoutMs en later werk wacht tot de adapter klaar is.
Te veel werk in de wachtrijNieuwe bewerkingen worden geweigerd met QUEUE_FULL in plaats van onbeperkt te groeien.

Saves op volgorde

Bewerkingen van één store overlappen nooit. Een save die start terwijl een andere wacht, neemt de nieuwste waarde, dus opslaan bij elke wijziging schrijft de laatste state zonder de wachtrij te vullen.

JavaScript / JSX
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 writes

Probeer het

Maak de opslag trager, laat schrijfacties mislukken of haal de opslag helemaal weg.

Voorbeeld voorbereiden…

Als laden mislukt

restateManager.ready wordt geweigerd met BULK_OPERATION_FAILED en noemt elke mislukte store. Totdat dat record laadt, vervangen autoSave en saveAll het niet en melden ze LOAD_FAILED.

Probeer opnieuw met initialize() om bewerkingen te houden en op te slaan, roep restore() aan om ze te verwerpen, of save() om het record bewust te overschrijven.

JavaScript / JSX
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);
  }
}

Opslaan en sluiten

Een save die vóór de unmount is aangevraagd, wordt toch afgemaakt, dus een handler voor „Opslaan en sluiten” hoeft niet te wachten.

JavaScript / JSX
function Document({ onClose }) {
  const useDraft = useRestateScope((scope) => persistedRestate('', { scope, key: 'draft' }));

  const saveAndClose = () => {
    useDraft.save(); // finishes even after this component unmounts
    onClose();
  };
  // …
}

Geen opslag beschikbaar

Server-rendering en door de browser geblokkeerde opslag zijn geen opstartfouten. Controleer available om gebruikers te vertellen dat bewerkingen alleen in het geheugen blijven.

JavaScript / JSX
const { available } = useDraft.status();

if (!available) {
  // Server rendering or blocked browser storage: the store works in memory
  // and save() rejects with STORAGE_UNAVAILABLE.
  showNotice('Changes are kept until you close this tab.');
}

Opgeslagen data valideren en migreren

version, migrate en validate beschermen je tegen oude of beschadigde records. validate draait vóór het opslaan en na terugzetten of migreren.

JavaScript / JSX
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),
  },
);

Je eigen opslag gebruiken

Elk object met getItem, setItem en removeItem werkt. De methoden mogen waarden of een Promise teruggeven; isAvailable is optioneel.

JavaScript / JSX
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,
  },
);

Limieten en time-outs

Stel in hoe lang een bewerking mag duren, hoeveel er mogen wachten en hoe groot een waarde mag zijn.

JavaScript / JSX
persistedRestate(value, {
  key: 'draft',
  operationTimeoutMs: 10_000, // default 30000
  maxPendingOperations: 64, // default 256
  maxStorageCharacters: 1_000_000,
});

Foutcodes

Fouten die restate aanmaakt hebben name RestateError, een code en, bij opgeslagen stores, key. Opslagadapters en je eigen callbacks kunnen weigeren met eigen fouten.

CodeBetekenis
BULK_OPERATION_FAILEDEen bulkaanroep zoals restateManager.ready of saveAll had fouten; zie error.failures.
INDEXEDDB_ABORTEDEen IndexedDB-transactie is afgebroken.
INDEXEDDB_BLOCKEDHet openen van de database werd geblokkeerd door een verbinding in een ander tabblad.
INDEXEDDB_CONNECTION_CLOSINGDe databaseverbinding werd gesloten toen het verzoek begon.
INDEXEDDB_OPEN_FAILEDDe database kon niet worden geopend.
INDEXEDDB_REQUEST_FAILEDEen IndexedDB-verzoek is mislukt.
INDEXEDDB_STORE_MISSINGDe object store ontbreekt in een al aangemaakte database.
INVALID_STORAGE_RECORDEen opgeslagen record is geen geldig restate-record.
INVALID_STORED_VALUEEen waarde kwam niet door validate.
LIFECYCLE_LIMITEen updater bleef starten en stoppen.
LOAD_FAILEDEen record kon niet laden, dus een automatische of bulksave heeft het niet vervangen.
MMKV_UNAVAILABLEreact-native-mmkv kon niet worden geladen.
MULTIPLE_ERRORSMeerdere callbacks mislukten in één bewerking; zie error.errors.
NOTIFICATION_LIMITObservers bleven in een lus wijzigingen inplannen.
OBSERVER_ERROREen listener of lifecycle-callback gooide een fout.
OPERATION_ABORTEDEen opslagbewerking is afgebroken.
QUEUE_FULLEr wachtten meer bewerkingen dan maxPendingOperations toestaat.
REENTRANT_SETTEREen state-updater probeerde dezelfde store te wijzigen terwijl hij draaide.
SCOPE_DESTROYEDEen vernietigde scope werd gebruikt om stores aan te maken.
SEQUENCE_EXHAUSTEDEen interne reeks had geen id's meer.
STORAGE_BLOCKEDEen eerdere adapteraanroep werd na een time-out of afbreking niet afgerond.
STORAGE_TIMEOUTEen bewerking duurde langer dan operationTimeoutMs.
STORAGE_UNAVAILABLEOpslag kan hier niet worden gebruikt; de store blijft in het geheugen werken.
STORAGE_VALUE_TOO_LARGEDe gecodeerde waarde overschrijdt maxStorageCharacters.
STORAGE_VERSION_MISMATCHEen record heeft een andere versie en geen migrate-functie die het afhandelt.
STORE_DESTROYEDEr werd geabonneerd op een vernietigde store of die werd gevraagd opslag te gebruiken.

Documentatie doorzoeken

Zoek in titels, beschrijvingen en de tekst van alle gidsen.