restate / v1.0.0
Niezawodność by design
Co gwarantuje restate, gdy pamięć jest wolna, zawodzi lub jej brak, i jak czytać zgłaszane błędy.
Na tej stronie
GwarancjeUporządkowane zapisyWypróbujGdy wczytanie się nie udaZapisz i zamknijBrak dostępnej pamięciWaliduj i migruj zapisane daneUżyj własnej pamięciLimity i limity czasuKody błędówGwarancje
Te zachowania są częścią kontraktu 1.0 i są objęte testami pakietu.
| Sytuacja | Co robi restate |
|---|---|
Kilka zapisów z rzędu | Wykonuje je po kolei dla każdego magazynu; zapis w kolejce zapisuje najnowszą wartość. |
Rekord się nie wczytał | autoSave i zapisy zbiorcze pomijają go z LOAD_FAILED; zastępuje go tylko jawne save(). |
Komponent odmontowuje się w trakcie zapisu | Zlecony zapis się kończy; późniejsze zapisy do zniszczonego magazynu są ignorowane. |
Pamięć jest niedostępna | Magazyn działa w pamięci operacyjnej, status().available jest false, zapisy są odrzucane. |
Adapter się zawiesza | Operacja kończy się po operationTimeoutMs, a kolejna praca czeka, aż adapter skończy. |
Za dużo oczekującej pracy | Nowe operacje są odrzucane z QUEUE_FULL zamiast rosnąć bez końca. |
Uporządkowane zapisy
Operacje jednego magazynu nigdy się nie nakładają. Zapis rozpoczęty, gdy inny czeka, bierze najnowszą wartość, więc zapis przy każdej zmianie zapisuje ostatni stan bez zapychania kolejki.
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 writesWypróbuj
Spowolnij pamięć, spraw, by zapisy się nie udawały, albo całkiem usuń pamięć.
Przygotowywanie przykładu…
Gdy wczytanie się nie uda
restateManager.ready jest odrzucane z BULK_OPERATION_FAILED i wymienia każdy magazyn z błędem. Dopóki ten rekord się nie wczyta, autoSave i saveAll go nie zastąpią i zgłoszą LOAD_FAILED.
Spróbuj ponownie przez initialize(), by zachować edycje i je zapisać, wywołaj restore(), by je odrzucić, albo save(), by celowo nadpisać rekord.
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);
}
}Zapisz i zamknij
Zapis zlecony przed odmontowaniem i tak się kończy, więc obsługa „Zapisz i zamknij” nie musi czekać.
function Document({ onClose }) {
const useDraft = useRestateScope((scope) => persistedRestate('', { scope, key: 'draft' }));
const saveAndClose = () => {
useDraft.save(); // finishes even after this component unmounts
onClose();
};
// …
}Waliduj i migruj zapisane dane
version, migrate i validate chronią przed starymi lub uszkodzonymi rekordami. validate uruchamia się przed zapisem oraz po przywróceniu lub migracji.
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),
},
);Użyj własnej pamięci
Nada się każdy obiekt z getItem, setItem i removeItem. Metody mogą zwracać wartości lub Promise; isAvailable jest opcjonalne.
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,
},
);Limity i limity czasu
Dostosuj, jak długo może trwać operacja, ile operacji może czekać i jak duża może być wartość.
persistedRestate(value, {
key: 'draft',
operationTimeoutMs: 10_000, // default 30000
maxPendingOperations: 64, // default 256
maxStorageCharacters: 1_000_000,
});Kody błędów
Błędy tworzone przez restate mają name RestateError, code oraz, w zapisywanych magazynach, key. Adaptery pamięci i twoje callbacki mogą odrzucać własnymi błędami.
| Kod | Znaczenie |
|---|---|
BULK_OPERATION_FAILED | Wywołanie zbiorcze, takie jak restateManager.ready lub saveAll, miało błędy; zobacz error.failures. |
INDEXEDDB_ABORTED | Transakcja IndexedDB została przerwana. |
INDEXEDDB_BLOCKED | Otwarcie bazy danych zablokowało połączenie w innej karcie. |
INDEXEDDB_CONNECTION_CLOSING | Połączenie z bazą danych było zamykane, gdy zaczęło się żądanie. |
INDEXEDDB_OPEN_FAILED | Nie udało się otworzyć bazy danych. |
INDEXEDDB_REQUEST_FAILED | Żądanie IndexedDB nie powiodło się. |
INDEXEDDB_STORE_MISSING | W już utworzonej bazie danych brakuje object store. |
INVALID_STORAGE_RECORD | Zapisany rekord nie jest prawidłowym rekordem restate. |
INVALID_STORED_VALUE | Wartość nie przeszła validate. |
LIFECYCLE_LIMIT | Updater w kółko startował i się zatrzymywał. |
LOAD_FAILED | Rekordu nie udało się wczytać, więc zapis automatyczny lub zbiorczy go nie zastąpił. |
MMKV_UNAVAILABLE | Nie udało się wczytać react-native-mmkv. |
MULTIPLE_ERRORS | W jednej operacji zawiodło kilka callbacków; zobacz error.errors. |
NOTIFICATION_LIMIT | Obserwatorzy w kółko planowali zmiany w pętli. |
OBSERVER_ERROR | Słuchacz lub callback cyklu życia rzucił błąd. |
OPERATION_ABORTED | Operacja na pamięci została anulowana. |
QUEUE_FULL | Czekało więcej operacji, niż pozwala maxPendingOperations. |
REENTRANT_SETTER | Updater stanu próbował zmienić ten sam magazyn w trakcie swojego działania. |
SCOPE_DESTROYED | Do tworzenia magazynów użyto zniszczonego zakresu. |
SEQUENCE_EXHAUSTED | Wewnętrznej sekwencji skończyły się identyfikatory. |
STORAGE_BLOCKED | Poprzednie wywołanie adaptera nie zakończyło się po przekroczeniu czasu lub anulowaniu. |
STORAGE_TIMEOUT | Operacja trwała dłużej niż operationTimeoutMs. |
STORAGE_UNAVAILABLE | Tutaj nie można użyć pamięci; magazyn działa dalej w pamięci operacyjnej. |
STORAGE_VALUE_TOO_LARGE | Zakodowana wartość przekracza maxStorageCharacters. |
STORAGE_VERSION_MISMATCH | Rekord ma inną wersję i żadna funkcja migrate jej nie obsługuje. |
STORE_DESTROYED | Zasubskrybowano zniszczony magazyn lub poproszono go o użycie pamięci. |