restate / v1.0.0

Надійність by design

Що гарантує restate, коли сховище повільне, дає збій або відсутнє, і як читати помилки, про які він повідомляє.

На цій сторінціГарантіїУпорядковані збереженняСпробуйтеЯкщо завантаження не вдалосяЗберегти й закритиСховище недоступнеВалідація й міграція збережених данихВласне сховищеЛіміти й тайм-аутиКоди помилок

Гарантії

Ця поведінка — частина контракту 1.0, і її покривають тести пакета.

СитуаціяЩо робить restate
Кілька збережень поспільВиконує їх по черзі для кожного сховища; збереження в черзі записує найсвіжіше значення.
Запис не завантаживсяautoSave і масові збереження пропускають його з LOAD_FAILED; замінює його лише явний save().
Компонент демонтується під час збереженняЗапитане збереження завершується; пізніші записи в знищене сховище ігноруються.
Сховище недоступнеСховище працює в пам’яті, status().available дорівнює false, збереження відхиляються.
Адаптер зависаєОперація завершується за тайм-аутом через operationTimeoutMs, а наступна робота чекає, доки адаптер закінчить.
Забагато роботи в очікуванніНові операції відхиляються з QUEUE_FULL замість безмежного зростання.

Упорядковані збереження

Операції одного сховища ніколи не перетинаються. Збереження, розпочате під час очікування іншого, бере найновіше значення, тож збереження за кожної зміни записує останній стан, не переповнюючи черги.

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

Спробуйте

Сповільніть сховище, змусьте записи падати або приберіть сховище зовсім.

Підготовка прикладу…

Якщо завантаження не вдалося

restateManager.ready відхиляється з BULK_OPERATION_FAILED і перелічує кожне сховище з помилкою. Доки цей запис не завантажиться, autoSave і saveAll його не замінюють і повідомляють LOAD_FAILED.

Повторіть через initialize(), щоб зберегти правки, викличте restore(), щоб їх відкинути, або save(), щоб навмисно перезаписати запис.

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

Зберегти й закрити

Збереження, запитане до демонтування, однаково завершиться, тож обробнику «Зберегти й закрити» не треба чекати.

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

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

Сховище недоступне

Рендеринг на сервері й сховище, заблоковане браузером, — не помилки запуску. Перевіряйте available, щоб повідомити користувачам, що правки лишаються лише в пам’яті.

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

Валідація й міграція збережених даних

version, migrate і validate захищають від старих чи пошкоджених записів. validate виконується перед збереженням і після відновлення чи міграції.

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

Власне сховище

Підійде будь-який об’єкт із getItem, setItem і removeItem. Методи можуть повертати значення або Promise; isAvailable необов’язковий.

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

Ліміти й тайм-аути

Налаштуйте, скільки може тривати операція, скільки їх може чекати й наскільки великим може бути значення.

JavaScript / JSX
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_LIMITUpdater знову й знову запускався й зупинявся.
LOAD_FAILEDЗапис не вдалося завантажити, тож автоматичне чи масове збереження його не замінило.
MMKV_UNAVAILABLEНе вдалося завантажити react-native-mmkv.
MULTIPLE_ERRORSВ одній операції впало кілька колбеків; див. error.errors.
NOTIFICATION_LIMITСпостерігачі раз у раз планували зміни в циклі.
OBSERVER_ERRORСлухач або колбек життєвого циклу кинув помилку.
OPERATION_ABORTEDОперацію зі сховищем скасовано.
QUEUE_FULLОперацій в очікуванні більше, ніж дозволяє maxPendingOperations.
REENTRANT_SETTERUpdater стану спробував змінити те саме сховище під час свого виконання.
SCOPE_DESTROYEDДля створення сховищ використано знищену область.
SEQUENCE_EXHAUSTEDВнутрішній послідовності забракло ідентифікаторів.
STORAGE_BLOCKEDПопередній виклик адаптера не завершився після тайм-ауту чи скасування.
STORAGE_TIMEOUTОперація тривала довше за operationTimeoutMs.
STORAGE_UNAVAILABLEТут сховище використовувати не можна; сховище й далі працює в пам’яті.
STORAGE_VALUE_TOO_LARGEЗакодоване значення перевищує maxStorageCharacters.
STORAGE_VERSION_MISMATCHЗапис має іншу версію, і жодна функція migrate її не обробляє.
STORE_DESTROYEDНа знищене сховище підписалися або попросили його використати сховище.

Пошук у документації

Пошук у заголовках, описах і тексті всіх посібників.