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ágina
Las 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 errorLas garantías
Estos comportamientos forman parte del contrato de la 1.0 y están cubiertos por los tests del paquete.
| Situación | Qué hace restate |
|---|---|
Varios guardados seguidos | Los ejecuta en orden por store; un guardado que espera en la cola escribe el valor más reciente. |
Un registro no se pudo cargar | autoSave y los guardados masivos lo omiten con LOAD_FAILED; solo un save() explícito lo reemplaza. |
El componente se desmonta durante un guardado | El guardado pedido termina; las escrituras posteriores en el store destruido se ignoran. |
El almacenamiento no está disponible | El store funciona en memoria, status().available es false y los guardados se rechazan. |
Un adaptador se cuelga | La operación expira tras operationTimeoutMs y el trabajo posterior espera a que el adaptador termine. |
Demasiado trabajo pendiente | Las 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.
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 writesPrué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.
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.
function Document({ onClose }) {
const useDraft = useRestateScope((scope) => persistedRestate('', { scope, key: 'draft' }));
const saveAndClose = () => {
useDraft.save(); // finishes even after this component unmounts
onClose();
};
// …
}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.
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.
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.
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ódigo | Significado |
|---|---|
BULK_OPERATION_FAILED | Una llamada masiva como restateManager.ready o saveAll tuvo fallos; consulta error.failures. |
INDEXEDDB_ABORTED | Se abortó una transacción de IndexedDB. |
INDEXEDDB_BLOCKED | Una conexión en otra pestaña bloqueó la apertura de la base de datos. |
INDEXEDDB_CONNECTION_CLOSING | La conexión con la base de datos se estaba cerrando cuando empezó la petición. |
INDEXEDDB_OPEN_FAILED | No se pudo abrir la base de datos. |
INDEXEDDB_REQUEST_FAILED | Falló una petición de IndexedDB. |
INDEXEDDB_STORE_MISSING | El almacén de objetos no existe en una base de datos ya creada. |
INVALID_STORAGE_RECORD | Un registro guardado no es un registro válido de restate. |
INVALID_STORED_VALUE | Un valor no superó validate. |
LIFECYCLE_LIMIT | Un updater no dejaba de arrancarse y detenerse. |
LOAD_FAILED | No se pudo cargar un registro, así que un guardado automático o masivo no lo reemplazó. |
MMKV_UNAVAILABLE | No se pudo cargar react-native-mmkv. |
MULTIPLE_ERRORS | Fallaron varios callbacks en una operación; consulta error.errors. |
NOTIFICATION_LIMIT | Los observadores siguieron programando cambios en bucle. |
OBSERVER_ERROR | Un listener o un callback del ciclo de vida lanzó un error. |
OPERATION_ABORTED | Se canceló una operación de almacenamiento. |
QUEUE_FULL | Había más operaciones esperando de las que permite maxPendingOperations. |
REENTRANT_SETTER | Un updater de estado intentó cambiar el mismo store mientras se ejecutaba. |
SCOPE_DESTROYED | Se usó un scope destruido para crear stores. |
SEQUENCE_EXHAUSTED | Una secuencia interna se quedó sin identificadores. |
STORAGE_BLOCKED | Una llamada anterior al adaptador no ha terminado tras un tiempo de espera o una cancelación. |
STORAGE_TIMEOUT | Una operación tardó más de operationTimeoutMs. |
STORAGE_UNAVAILABLE | Aquí no se puede usar el almacenamiento; el store sigue funcionando en memoria. |
STORAGE_VALUE_TOO_LARGE | El valor codificado supera maxStorageCharacters. |
STORAGE_VERSION_MISMATCH | Un registro tiene otra versión y ninguna función migrate lo gestiona. |
STORE_DESTROYED | Se intentó suscribirse a un store destruido o pedirle que usara el almacenamiento. |