restate / v1.0.0
Надійність by design
Що гарантує restate, коли сховище повільне, дає збій або відсутнє, і як читати помилки, про які він повідомляє.
На цій сторінці
ГарантіїУпорядковані збереженняСпробуйтеЯкщо завантаження не вдалосяЗберегти й закритиСховище недоступнеВалідація й міграція збережених данихВласне сховищеЛіміти й тайм-аутиКоди помилокГарантії
Ця поведінка — частина контракту 1.0, і її покривають тести пакета.
| Ситуація | Що робить restate |
|---|---|
Кілька збережень поспіль | Виконує їх по черзі для кожного сховища; збереження в черзі записує найсвіжіше значення. |
Запис не завантажився | autoSave і масові збереження пропускають його з LOAD_FAILED; замінює його лише явний save(). |
Компонент демонтується під час збереження | Запитане збереження завершується; пізніші записи в знищене сховище ігноруються. |
Сховище недоступне | Сховище працює в пам’яті, status().available дорівнює false, збереження відхиляються. |
Адаптер зависає | Операція завершується за тайм-аутом через operationTimeoutMs, а наступна робота чекає, доки адаптер закінчить. |
Забагато роботи в очікуванні | Нові операції відхиляються з QUEUE_FULL замість безмежного зростання. |
Упорядковані збереження
Операції одного сховища ніколи не перетинаються. Збереження, розпочате під час очікування іншого, бере найновіше значення, тож збереження за кожної зміни записує останній стан, не переповнюючи черги.
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Спробуйте
Сповільніть сховище, змусьте записи падати або приберіть сховище зовсім.
Підготовка прикладу…
Якщо завантаження не вдалося
restateManager.ready відхиляється з BULK_OPERATION_FAILED і перелічує кожне сховище з помилкою. Доки цей запис не завантажиться, autoSave і saveAll його не замінюють і повідомляють LOAD_FAILED.
Повторіть через initialize(), щоб зберегти правки, викличте restore(), щоб їх відкинути, або save(), щоб навмисно перезаписати запис.
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);
}
}Зберегти й закрити
Збереження, запитане до демонтування, однаково завершиться, тож обробнику «Зберегти й закрити» не треба чекати.
function Document({ onClose }) {
const useDraft = useRestateScope((scope) => persistedRestate('', { scope, key: 'draft' }));
const saveAndClose = () => {
useDraft.save(); // finishes even after this component unmounts
onClose();
};
// …
}Валідація й міграція збережених даних
version, migrate і validate захищають від старих чи пошкоджених записів. validate виконується перед збереженням і після відновлення чи міграції.
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),
},
);Власне сховище
Підійде будь-який об’єкт із getItem, setItem і removeItem. Методи можуть повертати значення або Promise; isAvailable необов’язковий.
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,
},
);Ліміти й тайм-аути
Налаштуйте, скільки може тривати операція, скільки їх може чекати й наскільки великим може бути значення.
persistedRestate(value, {
key: 'draft',
operationTimeoutMs: 10_000, // default 30000
maxPendingOperations: 64, // default 256
maxStorageCharacters: 1_000_000,
});Коди помилок
Помилки, створені restate, мають name RestateError, code і, для збережуваних сховищ, key. Адаптери сховища й ваші колбеки можуть відхилятися власними помилками.
| Код | Значення |
|---|---|
BULK_OPERATION_FAILED | У масовому виклику, як-от restateManager.ready чи saveAll, були помилки; див. error.failures. |
INDEXEDDB_ABORTED | Транзакцію IndexedDB перервано. |
INDEXEDDB_BLOCKED | Відкриття бази даних заблоковано з’єднанням в іншій вкладці. |
INDEXEDDB_CONNECTION_CLOSING | З’єднання з базою даних закривалося, коли почався запит. |
INDEXEDDB_OPEN_FAILED | Не вдалося відкрити базу даних. |
INDEXEDDB_REQUEST_FAILED | Запит IndexedDB не вдався. |
INDEXEDDB_STORE_MISSING | У вже створеній базі даних немає object store. |
INVALID_STORAGE_RECORD | Збережений запис не є коректним записом restate. |
INVALID_STORED_VALUE | Значення не пройшло validate. |
LIFECYCLE_LIMIT | Updater знову й знову запускався й зупинявся. |
LOAD_FAILED | Запис не вдалося завантажити, тож автоматичне чи масове збереження його не замінило. |
MMKV_UNAVAILABLE | Не вдалося завантажити react-native-mmkv. |
MULTIPLE_ERRORS | В одній операції впало кілька колбеків; див. error.errors. |
NOTIFICATION_LIMIT | Спостерігачі раз у раз планували зміни в циклі. |
OBSERVER_ERROR | Слухач або колбек життєвого циклу кинув помилку. |
OPERATION_ABORTED | Операцію зі сховищем скасовано. |
QUEUE_FULL | Операцій в очікуванні більше, ніж дозволяє maxPendingOperations. |
REENTRANT_SETTER | Updater стану спробував змінити те саме сховище під час свого виконання. |
SCOPE_DESTROYED | Для створення сховищ використано знищену область. |
SEQUENCE_EXHAUSTED | Внутрішній послідовності забракло ідентифікаторів. |
STORAGE_BLOCKED | Попередній виклик адаптера не завершився після тайм-ауту чи скасування. |
STORAGE_TIMEOUT | Операція тривала довше за operationTimeoutMs. |
STORAGE_UNAVAILABLE | Тут сховище використовувати не можна; сховище й далі працює в пам’яті. |
STORAGE_VALUE_TOO_LARGE | Закодоване значення перевищує maxStorageCharacters. |
STORAGE_VERSION_MISMATCH | Запис має іншу версію, і жодна функція migrate її не обробляє. |
STORE_DESTROYED | На знищене сховище підписалися або попросили його використати сховище. |