restate / v1.0.0

Confiabilidade desde o design

O que o restate garante quando o armazenamento é lento, falha ou não existe, e como ler os erros que ele informa.

Nesta páginaAs garantiasSalvamentos em ordemExperimenteQuando o carregamento falhaSalvar e fecharNenhum armazenamento disponívelValide e migre dados salvosUse seu próprio armazenamentoLimites e tempos de esperaCódigos de erro

As garantias

Esses comportamentos fazem parte do contrato da versão 1.0 e são cobertos pelos testes do pacote.

SituaçãoO que o restate faz
Vários salvamentos seguidosExecuta em ordem por store; um salvamento esperando na fila grava o valor mais recente.
Um registro não carregouO autoSave e os salvamentos em lote o ignoram com LOAD_FAILED; só um save() explícito o substitui.
O componente é desmontado durante um salvamentoO salvamento pedido termina; gravações posteriores no store destruído são ignoradas.
O armazenamento está indisponívelO store funciona em memória, status().available é false e os salvamentos são rejeitados.
Um adaptador travaA operação expira depois de operationTimeoutMs e o trabalho seguinte espera o adaptador terminar.
Trabalho pendente demaisNovas operações são rejeitadas com QUEUE_FULL em vez de crescer sem limite.

Salvamentos em ordem

As operações de um store nunca se sobrepõem. Um salvamento disparado enquanto outro espera pega o valor mais novo, então salvar a cada mudança grava o estado mais recente sem encher a fila.

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

Experimente

Deixe o armazenamento lento, faça as gravações falharem ou remova o armazenamento de vez.

Preparando o exemplo…

Quando o carregamento falha

restateManager.ready é rejeitado com BULK_OPERATION_FAILED e lista cada store que falhou. Até esse registro carregar, o autoSave e o saveAll não o substituem e informam LOAD_FAILED.

Tente de novo com initialize() para manter suas edições e salvá-las, chame restore() para descartá-las ou save() para sobrescrever o registro de propósito.

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);
  }
}

Salvar e fechar

Um salvamento pedido antes da desmontagem termina mesmo assim, então um handler de “Salvar e fechar” não precisa esperar.

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

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

Nenhum armazenamento disponível

Renderização no servidor e armazenamento bloqueado no navegador não são erros na inicialização. Verifique available para avisar os usuários de que as alterações ficam só na memória.

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.');
}

Valide e migre dados salvos

version, migrate e validate protegem você de registros antigos ou corrompidos. validate roda antes de salvar e depois de restaurar ou migrar.

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

Use seu próprio armazenamento

Qualquer objeto com getItem, setItem e removeItem serve. Os métodos podem retornar valores ou Promises; isAvailable é opcional.

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

Limites e tempos de espera

Ajuste quanto tempo uma operação pode durar, quantas podem esperar e qual o tamanho máximo de um valor.

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

Códigos de erro

Erros criados pelo restate têm name RestateError, um code e, nos stores salvos, key. Adaptadores de armazenamento e seus callbacks podem rejeitar com os próprios erros.

CódigoSignificado
BULK_OPERATION_FAILEDUma chamada em lote como restateManager.ready ou saveAll teve falhas; veja error.failures.
INDEXEDDB_ABORTEDUma transação do IndexedDB foi abortada.
INDEXEDDB_BLOCKEDA abertura do banco foi bloqueada por uma conexão em outra aba.
INDEXEDDB_CONNECTION_CLOSINGA conexão com o banco estava fechando quando a requisição começou.
INDEXEDDB_OPEN_FAILEDNão foi possível abrir o banco de dados.
INDEXEDDB_REQUEST_FAILEDUma requisição do IndexedDB falhou.
INDEXEDDB_STORE_MISSINGO object store não existe em um banco já criado.
INVALID_STORAGE_RECORDUm registro salvo não é um registro válido do restate.
INVALID_STORED_VALUEUm valor não passou no validate.
LIFECYCLE_LIMITUm updater ficou iniciando e parando sem parar.
LOAD_FAILEDUm registro não pôde ser carregado, então um salvamento automático ou em lote não o substituiu.
MMKV_UNAVAILABLENão foi possível carregar react-native-mmkv.
MULTIPLE_ERRORSVários callbacks falharam em uma operação; veja error.errors.
NOTIFICATION_LIMITObservadores continuaram agendando mudanças em loop.
OBSERVER_ERRORUm listener ou callback de ciclo de vida lançou um erro.
OPERATION_ABORTEDUma operação de armazenamento foi cancelada.
QUEUE_FULLHavia mais operações esperando do que maxPendingOperations permite.
REENTRANT_SETTERUm updater de estado tentou mudar o mesmo store enquanto rodava.
SCOPE_DESTROYEDUm scope destruído foi usado para criar stores.
SEQUENCE_EXHAUSTEDUma sequência interna ficou sem identificadores.
STORAGE_BLOCKEDUma chamada anterior ao adaptador não terminou depois de um tempo esgotado ou cancelamento.
STORAGE_TIMEOUTUma operação demorou mais que operationTimeoutMs.
STORAGE_UNAVAILABLEO armazenamento não pode ser usado aqui; o store continua funcionando em memória.
STORAGE_VALUE_TOO_LARGEO valor codificado é maior que maxStorageCharacters.
STORAGE_VERSION_MISMATCHUm registro tem outra versão e nenhuma função migrate trata dela.
STORE_DESTROYEDHouve tentativa de assinar um store destruído ou de pedir que ele usasse o armazenamento.

Pesquisar na documentação

Pesquisa em títulos, descrições e texto de todos os guias.