restate / v1.0.0
Надеждност by design
Какво гарантира restate, когато хранилището е бавно, отказва или липсва, и как да четете грешките, които съобщава.
На тази страница
ГаранциитеПодредени запазванияОпитайтеКогато зареждането се провалиЗапази и затвориНяма налично хранилищеВалидиране и мигриране на запазени данниСобствено хранилищеОграничения и изчакванеКодове на грешкиГаранциите
Това поведение е част от договора на 1.0 и е покрито от тестовете на пакета.
| Ситуация | Какво прави restate |
|---|---|
Няколко запазвания едно след друго | Изпълнява ги по ред за всеки store; запазване в опашката записва най-новата стойност. |
Запис не се е заредил | autoSave и груповите запазвания го пропускат с LOAD_FAILED; замества го само изрично save(). |
Компонентът се демонтира по време на запазване | Поисканото запазване завършва; по-късните записи в унищожения store се игнорират. |
Хранилището е недостъпно | Store работи в паметта, status().available е false, а запазванията се отхвърлят. |
Адаптерът зависва | Операцията изтича след operationTimeoutMs, а следващата работа чака, докато адаптерът приключи. |
Твърде много чакаща работа | Новите операции се отхвърлят с QUEUE_FULL, вместо да растат безкрайно. |
Подредени запазвания
Операциите на един store никога не се застъпват. Запазване, започнало, докато друго чака, взема най-новата стойност, така че запазването при всяка промяна записва последното състояние, без да пълни опашката.
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 и изброява всеки store с грешка. Докато този запис не се зареди, 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 и, при запазваните store, key. Адаптерите за хранилище и вашите callback-и могат да отхвърлят със собствени грешки.
| Код | Значение |
|---|---|
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 | В една операция са се провалили няколко callback-а; вижте error.errors. |
NOTIFICATION_LIMIT | Наблюдателите продължаваха да планират промени в цикъл. |
OBSERVER_ERROR | Слушател или callback на жизнения цикъл е хвърлил грешка. |
OPERATION_ABORTED | Операция с хранилището е отменена. |
QUEUE_FULL | Чакащите операции са повече, отколкото позволява maxPendingOperations. |
REENTRANT_SETTER | Updater на състоянието е опитал да промени същия store, докато се изпълнява. |
SCOPE_DESTROYED | Унищожен scope е използван за създаване на store. |
SEQUENCE_EXHAUSTED | Вътрешна последователност е изчерпала идентификаторите. |
STORAGE_BLOCKED | Предишно извикване на адаптера не е приключило след изтичане на времето или отмяна. |
STORAGE_TIMEOUT | Операция е продължила по-дълго от operationTimeoutMs. |
STORAGE_UNAVAILABLE | Тук хранилището не може да се използва; store продължава да работи в паметта. |
STORAGE_VALUE_TOO_LARGE | Кодираната стойност надхвърля maxStorageCharacters. |
STORAGE_VERSION_MISMATCH | Записът има друга версия и никоя функция migrate не я обработва. |
STORE_DESTROYED | Има абониране за унищожен store или той е помолен да използва хранилище. |