restate / v1.0.0

Fiabilidad por diseño

Qué garantiza restate cuando el almacenamiento es lento, falla o no existe, y cómo leer los errores que informa.

En esta páginaLas garantíasGuardados en ordenPruébaloCuando falla la cargaGuardar y cerrarSin almacenamiento disponibleValida y migra los datos guardadosUsa tu propio almacenamientoLímites y tiempos de esperaCódigos de error

Las garantías

Estos comportamientos forman parte del contrato de la 1.0 y están cubiertos por los tests del paquete.

SituaciónQué hace restate
Varios guardados seguidosLos ejecuta en orden por store; un guardado que espera en la cola escribe el valor más reciente.
Un registro no se pudo cargarautoSave y los guardados masivos lo omiten con LOAD_FAILED; solo un save() explícito lo reemplaza.
El componente se desmonta durante un guardadoEl guardado pedido termina; las escrituras posteriores en el store destruido se ignoran.
El almacenamiento no está disponibleEl store funciona en memoria, status().available es false y los guardados se rechazan.
Un adaptador se cuelgaLa operación expira tras operationTimeoutMs y el trabajo posterior espera a que el adaptador termine.
Demasiado trabajo pendienteLas nuevas operaciones se rechazan con QUEUE_FULL en lugar de crecer sin límite.

Guardados en orden

Las operaciones de un store nunca se solapan. Un guardado emitido mientras otro espera toma el valor más nuevo, así que guardar en cada cambio escribe el último estado sin llenar la cola.

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

Pruébalo

Ralentiza el almacenamiento, haz que las escrituras fallen o quítalo por completo.

Preparando el ejemplo…

Cuando falla la carga

restateManager.ready se rechaza con BULK_OPERATION_FAILED y enumera cada store que falló. Hasta que ese registro se cargue, autoSave y saveAll no lo reemplazan e informan LOAD_FAILED.

Reintenta con initialize() para conservar tus ediciones y guardarlas, llama a restore() para descartarlas o a save() para sobrescribir el registro a 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);
  }
}

Guardar y cerrar

Un guardado pedido antes del desmontaje termina igualmente, así que un manejador de «Guardar y cerrar» no necesita 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();
  };
  // …
}

Sin almacenamiento disponible

El renderizado en servidor y el almacenamiento bloqueado del navegador no son errores al arrancar. Comprueba available para avisar a los usuarios de que los cambios solo se guardan en memoria.

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

Valida y migra los datos guardados

version, migrate y validate te protegen de registros antiguos o corruptos. validate se ejecuta antes de guardar y después de restaurar o 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),
  },
);

Usa tu propio almacenamiento

Sirve cualquier objeto con getItem, setItem y removeItem. Los métodos pueden devolver valores o Promises; isAvailable es 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,
  },
);

Límites y tiempos de espera

Ajusta cuánto puede durar una operación, cuántas pueden esperar y qué tamaño puede tener un valor.

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

Códigos de error

Los errores que crea restate tienen name RestateError, un code y, en los stores guardados, key. Los adaptadores de almacenamiento y tus callbacks pueden rechazar con sus propios errores.

CódigoSignificado
BULK_OPERATION_FAILEDUna llamada masiva como restateManager.ready o saveAll tuvo fallos; consulta error.failures.
INDEXEDDB_ABORTEDSe abortó una transacción de IndexedDB.
INDEXEDDB_BLOCKEDUna conexión en otra pestaña bloqueó la apertura de la base de datos.
INDEXEDDB_CONNECTION_CLOSINGLa conexión con la base de datos se estaba cerrando cuando empezó la petición.
INDEXEDDB_OPEN_FAILEDNo se pudo abrir la base de datos.
INDEXEDDB_REQUEST_FAILEDFalló una petición de IndexedDB.
INDEXEDDB_STORE_MISSINGEl almacén de objetos no existe en una base de datos ya creada.
INVALID_STORAGE_RECORDUn registro guardado no es un registro válido de restate.
INVALID_STORED_VALUEUn valor no superó validate.
LIFECYCLE_LIMITUn updater no dejaba de arrancarse y detenerse.
LOAD_FAILEDNo se pudo cargar un registro, así que un guardado automático o masivo no lo reemplazó.
MMKV_UNAVAILABLENo se pudo cargar react-native-mmkv.
MULTIPLE_ERRORSFallaron varios callbacks en una operación; consulta error.errors.
NOTIFICATION_LIMITLos observadores siguieron programando cambios en bucle.
OBSERVER_ERRORUn listener o un callback del ciclo de vida lanzó un error.
OPERATION_ABORTEDSe canceló una operación de almacenamiento.
QUEUE_FULLHabía más operaciones esperando de las que permite maxPendingOperations.
REENTRANT_SETTERUn updater de estado intentó cambiar el mismo store mientras se ejecutaba.
SCOPE_DESTROYEDSe usó un scope destruido para crear stores.
SEQUENCE_EXHAUSTEDUna secuencia interna se quedó sin identificadores.
STORAGE_BLOCKEDUna llamada anterior al adaptador no ha terminado tras un tiempo de espera o una cancelación.
STORAGE_TIMEOUTUna operación tardó más de operationTimeoutMs.
STORAGE_UNAVAILABLEAquí no se puede usar el almacenamiento; el store sigue funcionando en memoria.
STORAGE_VALUE_TOO_LARGEEl valor codificado supera maxStorageCharacters.
STORAGE_VERSION_MISMATCHUn registro tiene otra versión y ninguna función migrate lo gestiona.
STORE_DESTROYEDSe intentó suscribirse a un store destruido o pedirle que usara el almacenamiento.

Buscar en la documentación

Busca en títulos, descripciones y texto de todas las guías.