Zdalne przechowywanie
Wysyłanie całego stanu edytora przy każdej zmianie jest nieefektywne.
Z myślą o takich przypadkach edytor udostępnia interfejs API do replikacji danych w czasie rzeczywistym.
Instalacja
npm install @dineug/erd-editor
Magazyn replikacji jest dostępny pod ścieżką podrzędną @dineug/erd-editor/engine.js, a nie w głównym module pakietu.
Ten punkt wejścia nie korzysta z drzewa DOM, więc działa w wątku Web Worker lub w dowolnym innym miejscu poza wątkiem głównym.
Import głównego modułu pakietu wymaga natomiast dokumentu: od wersji 5.0.0 nie definiuje żadnego elementu, ale jego wykonanie buduje obie klasy elementów. Przed wersją 5.0.0 rejestrował element niestandardowy <erd-editor>.
Użycie
type ReplicationStore = {
readonly value: string;
readonly runtimeValue: string;
on: (
listeners: Partial<{ change: (change: ReplicationChange) => void }>
) => Unsubscribe;
setInitialValue: (value: string) => void;
dispatch: (actions: Array<AnyAction> | AnyAction) => void;
dispatchSync: (actions: Array<AnyAction> | AnyAction) => void;
destroy: () => void;
};
type ReplicationChange = {
value: string;
changed: boolean;
};
type InjectEngineContext = {
toWidth: (text: string) => number;
};
type CreateReplicationStore = (
context: InjectEngineContext
) => ReplicationStore;
// example
import { createReplicationStore } from '@dineug/erd-editor/engine.js';
const replicationStore = createReplicationStore({
toWidth: text => text.length * 10,
});
Replikowanie działającego edytora
Akcje pochodzą ze współdzielonego magazynu działającego edytora.
Zobacz stronę Wspólna edycja.
import { createReplicationStore } from '@dineug/erd-editor/engine.js';
const replicationStore = createReplicationStore({ toWidth });
replicationStore.setInitialValue(editor.runtimeValue);
replicationStore.on({
change: ({ value, changed }) => {
if (changed) save(value);
},
});
const sharedStore = editor.getSharedStore();
sharedStore.subscribe(actions => {
replicationStore.dispatch(actions);
});
Granicę przekracza tylko zmiana, nigdy cały dokument.
Replika stosuje ją i serializuje wynik po swojej stronie.
Zdarzenie change przekazuje ten wynik jako value, a pole changed informuje, kiedy warto go zapisać.
Od wersji 4.0.0 inicjuj replikę na podstawie właściwości runtimeValue edytora, tak jak powyżej, a nie na podstawie zapisanego pliku ani właściwości value edytora.
W pliku brakuje zmian wprowadzonych od jego zapisania, a we właściwości value – encji usuniętych w trakcie sesji.
Replika zainicjowana bez usuniętej tabeli przywraca ją bez nazwy ani kolumn, gdy edytor cofnie usunięcie, i w takiej postaci ją zapisuje.
Od wersji 4.2.0 to samo dotyczy słowa, terminu lub domeny usuniętych z arkusza karty Słownik.
Gdy edytor cofnie usunięcie, replika zainicjowana bez tego wiersza przywraca go jako pusty, a ponieważ value pomija pusty wiersz, replika zapisuje dokument bez niego.
W przypadku domeny kolumny i terminy, które były z nią powiązane, również pozostają w tej replice niepowiązane, ponieważ replika nigdy nie miała tych powiązań, a cofnięcie ich nie wysyła.
Od wersji 5.1.0 pakiet @dineug/erd-editor-yjs może też synchronizować edytory za pośrednictwem pokoju Yjs.
Replika zasilana jak powyżej z elementu powiązanego z pokojem otrzymuje tylko edycje wykonane na tym elemencie, nigdy te, które przynosi pokój: docierają one do elementu jako edycje innego edytora, a współdzielony magazyn nie przekazuje dalej tego, co otrzymał.
Aby przechować dokument pokoju, zapisz właściwość value powiązanego elementu lub powiązanego magazynu uczestnika, jak opisano w sekcji Co zawiera pokój.
Dostawca trwałego przechowywania Yjs przechowuje sam pokój, który zawiera wartość czasu wykonania i edycje wykonane od jej powstania, a nie plik; zobacz sekcję Ograniczenia.
InjectEngineContext
toWidth
Mierzy szerokość ciągu znaków w pikselach.
Magazyn nie ma drzewa DOM, więc nie może sam mierzyć tekstu, a szerokości kolumn przelicza za pomocą tej funkcji przy każdej zmianie nazwy, typu danych, wartości domyślnej lub komentarza.
Od wersji 4.2.0 obejmuje to też nazwę logiczną tabeli lub kolumny.
Komórkę domeny kolumny, która pokazuje nazwę domeny powiązanej z kolumną, mierzy za każdym razem, gdy kolumna zostaje powiązana z domeną lub od niej odłączona, oraz za każdym razem, gdy ta domena zostaje dodana, otrzymuje nową nazwę lub zostaje usunięta.
Ponownie mierzy też każdą tabelę i kolumnę za każdym razem, gdy metoda setInitialValue wczytuje dokument.
Od wersji 4.0.0 szerokości są przechowywane tylko we właściwości runtimeValue, nigdy w value.
Dlatego dokument zapisany w tej wersji po ponownym wczytaniu daje bajt w bajt tę samą wartość value, niezależnie od tego, gdzie go zapisano i jak mierzono tam tekst.
Mierz tak jak edytor – 400 12px w stosie czcionek edytora, z zaokrągleniem i dodaniem 2 px dopełnienia.
W przeciwnym razie szerokości w runtimeValue zaczną odbiegać od tych widocznych na ekranie.
const TEXT_PADDING = 2;
const FONT =
"400 12px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, " +
"'Helvetica Neue', 'Open Sans', system-ui, sans-serif, " +
"'Apple Color Emoji', 'Segoe UI Emoji'";
let context = null;
function getContext() {
if (context) return context;
try {
context = new OffscreenCanvas(0, 0).getContext('2d');
if (context) context.font = FONT;
} catch {
// no canvas available
}
return context;
}
function toWidth(text) {
const context = getContext();
const width = context ? context.measureText(text).width : text.length * 10;
return Math.round(width) + TEXT_PADDING;
}
const replicationStore = createReplicationStore({ toWidth });
Wyrażenie text.length * 10 jest rozwiązaniem awaryjnym, gdy żadna kanwa nie jest dostępna.
To wystarczy w przypadku magazynu, którego dokument jest tylko przechowywany, a nigdy renderowany.
ReplicationStore
value getter
Serializuje bieżący stan edytora.
Zwraca ciąg znaków JSON gotowy do zapisania w niezmienionej postaci – a nie sparsowany obiekt.
const data = replicationStore.value;
Od wersji 4.0.0 właściwość value jest postacią zapisu: to dokument w takiej postaci, w jakiej zawiera go plik, czyli ten sam tekst, który zwraca właściwość value elementu.
Zawiera tylko nieusunięte encje, w ustalonej kolejności, bez encji usuniętych, kolejności warstw ani niczego, co wczytanie wylicza ponownie, na przykład szerokości mierzonych przez funkcję toWidth.
Od wersji 4.2.0 zawiera też nazwy logiczne, informację, czy każdą nazwę wygenerowano na podstawie słowników, powiązania z domenami oraz słowa, terminy i domeny karty Słownik.
Od wersji 4.2.0 pomija też każde puste pole tekstowe encji, każdą pustą listę doc i każdą pustą kolekcję, a także samo pole collections, gdy wszystkie kolekcje są puste.
Ma wcięcia o szerokości dwóch spacji, zapisuje każdy wiersz słownika w osobnej linii i kończy się znakiem nowego wiersza, więc ten sam dokument zawsze daje te same bajty.
Informacje o tym, co zawiera, znajdziesz w sekcji Postać zapisu.
Każde ustawienie, którego blokada jest włączona, zapisuje się z wartością, przy której zostało zablokowane, a każde inne – z bieżącą wartością.
Blokada Viewport obejmuje łącznie położenie widoku i poziom powiększenia, a karta, język Generatora kodu, oba style nazw i typ cudzysłowu mają własne, osobne blokady.
Od wersji 4.2.0 własną blokadę ma też Widok nazw, którego blokada Name View jest w nowym dokumencie włączona.
Blokady zastępują pole ignoreSaveSettings dokumentu, które od wersji 4.0.0 nie jest ani odczytywane, ani zapisywane.
Przed wersją 4.0.0 właściwość value była całym dokumentem w postaci, w jakiej przechowywał go magazyn, z zastosowanymi bitami przewijania i powiększenia z tego pola.
runtimeValue getter
Od wersji 4.0.0 serializuje dokument w postaci, w jakiej przechowuje go replika, łącznie z usuniętymi encjami i wszystkim, co wylicza wczytanie.
Każde zablokowane ustawienie także tutaj zapisuje się z zablokowaną wartością.
const snapshot = replicationStore.runtimeValue;
Używaj tej wartości do inicjowania edytora lub innego magazynu, który dołącza później, za pomocą jego metody setInitialValue; zobacz stronę Wspólna edycja.
Replika nie ma metod getLWW ani getVersion, więc wraz z runtimeValue nie przekazuje rejestrów współpracy: edytor zainicjowany na jej podstawie pobiera je od działających edytorów, jak opisano w sekcji Inicjowanie edytora współpracownika.
Nigdy nie zapisuj jej jako pliku: zawiera usunięte encje, a opublikowany schemat JSON Schema ją odrzuca.
To właśnie dzięki tym usuniętym encjom cofnięcie usunięcia, wysłane później, przywraca encję w całości w magazynie zainicjowanym na podstawie tej wartości.
Pozostają do czasu, aż dokument zostanie ponownie otwarty z pliku, którego postać ich nie zawiera.
setInitialValue
Wczytuje wcześniej zapisany stan edytora.
replicationStore.setInitialValue('json...');
Przyjmuje postać zapisu, wartość czasu wykonania lub dokument zapisany przez wcześniejszą wersję, w tym dokument v2.
Pusty ciąg znaków lub cokolwiek, co nie jest ciągiem znaków, wczytuje nowy, pusty dokument zamiast zgłosić błąd.
Magazyn, któremu nigdy nie przekazano wartości, zaczyna od takiego samego nowego dokumentu.
Od wersji 4.0.0 w takim dokumencie każda blokada jest włączona, więc jego właściwość value zachowuje widok, kartę, język Generatora kodu, style nazw i typ cudzysłowu, z jakimi zaczynał, gdy edytory, które magazyn replikuje, przewijają widok, zmieniają powiększenie, przełączają karty lub zmieniają te ustawienia. W wersji 3.10.0 nie zapisywał ani przewinięcia, ani powiększenia, a wcześniej zapisywał jedno i drugie.
Od wersji 4.2.0 zachowuje też swój Widok nazw, czyli widok Physical Names, gdy edytory przełączają własne.
Zapisany dokument zachowuje blokady, które wymienia.
Dokument, który nie wymienia żadnej, czyli każdy dokument zapisany przed wersją 4.0.0, w tym dokument v2, wczytuje się z włączonymi wszystkimi blokadami: z położeniem widoku 0, 0, poziomem powiększenia 1 i kartą ERD, niezależnie od tego, co zapisał, oraz z językiem Generatora kodu, stylami nazw i typem cudzysłowu w takiej postaci, w jakiej je zapisał.
Dokument zapisany przed wersją 4.2.0 nie wymienia blokady Name View, więc wczytuje się z tą blokadą włączoną i w widoku Physical Names, nawet jeśli zapisano go z wyłączonymi wszystkimi pozostałymi blokadami.
Od wersji 4.0.0 metoda setInitialValue usuwa też rejestry współpracy przechowywane dla poprzedniego dokumentu, tak jak metoda setInitialValue elementu.
Tekst, który nie jest w formacie JSON, na przykład plik pozostawiony ze znacznikami konfliktu scalania, również nie powoduje zgłoszenia błędu: błąd parsowania trafia tylko do konsoli, dokument zostaje opróżniony, a ustawienia pozostają bez zmian.
Od wersji 4.0.0 wczytywanie nie uruchamia odśmiecania, więc usunięte encje pozostają we właściwości runtimeValue.
Wcześniej usuwało encje, które nie występowały już w polu doc i nie były zmieniane od co najmniej czterech dni.
Przeliczenia wykonywane podczas wczytywania są gotowe, zanim metoda setInitialValue zwróci sterowanie: oznaczenia kluczy na kolumnach, odczytywane z opcji każdej kolumny i z relacji; szerokość każdej tabeli i kolumny, mierzona ponownie za pomocą toWidth; punkty, w których każdy łącznik styka się ze swoimi tabelami; oraz w każdej relacji flaga określająca, czy jest ona identyfikująca, i symbol na końcu przy tabeli nadrzędnej.
Żadne z nich nie wchodzi w skład value, ale wartość replicationStore.runtimeValue odczytana zaraz po wywołaniu zawiera już je wszystkie.
Akcja, która nadejdzie tuż po wczytaniu, na przykład odtworzone przewinięcie, jest porównywana z wczytanym dokumentem, więc samo wczytanie nigdy nie jest zgłaszane jako changed.
Ani wczytanie, ani żadne z tych przeliczeń nie emituje zdarzenia change.
Jeśli chcesz ponownie zapisać wczytany dokument w postaci zapisu, sam odczytaj replicationStore.value, gdy metoda setInitialValue zwróci sterowanie.
on@change
Subskrybuje zmiany stanu edytora.
const unsubscribe = replicationStore.on({
change: ({ value, changed }) => {
if (changed) {
// save value...
}
},
});
Zdarzenie change jest opóźniane (debounce) o 200 ms, więc seria akcji dociera jako jedno powiadomienie.
Jest wywoływane tylko dla akcji takiego rodzaju, który może zmienić dokument, a także dla akcji settings.changeIgnoreSaveSettings, którą starszy edytor może nadal wysyłać (zobacz sekcję dispatch, dispatchSync).
Nigdy nie wywołuje go przekazana akcja obecności ani akcja editor.mergeLWW.
Aby anulować subskrypcję, wywołaj zwróconą funkcję.
Od wersji 3.10.0 funkcja nasłuchująca otrzymuje wartość typu ReplicationChange, który @dineug/erd-editor/engine.js eksportuje obok typu ReplicationStore.
Przed wersją 3.10.0 nie otrzymywała niczego, a funkcja nasłuchująca, która ignoruje argument, nadal działa.
Pole value to zserializowany dokument w postaci zapisu, ten sam ciąg znaków, który w tym momencie zwraca replicationStore.value, więc nie trzeba go ponownie serializować.
Pole changed ma wartość false, gdy akcje od poprzedniego zdarzenia change lub od wczytania pozostawiły value bajt w bajt bez zmian.
Zmiana, którą blokada pomija w value, nadal wywołuje zdarzenie change z polem changed ustawionym na false, więc zapisuj tylko wtedy, gdy changed ma wartość true.
Chodzi o przewinięcie lub zmianę powiększenia przy zablokowanym ustawieniu Viewport, przełączenie karty przy zablokowanym ustawieniu Canvas Type oraz zmianę języka Generatora kodu, stylu nazw lub typu cudzysłowu przy włączonej blokadzie danego ustawienia, co od wersji 5.1.0 wysyła już tylko edytor w wersji starszej niż 5.1.0 (zobacz sekcję dispatch, dispatchSync).
Od wersji 4.2.0 chodzi też o przełączenie Widoku nazw przy zablokowanym ustawieniu Name View: edytor nadal je wysyła, ale replika je pomija, tak jak robią to pozostałe edytory.
Przełączenie Widoku nazw wykonane w edytorze tylko do odczytu jest pomijane w ten sam sposób, niezależnie od stanu jego blokady.
Zdarzenie change elementu pomija taką zmianę, ale replika nadal ją zgłasza.
W nowym dokumencie i w dokumencie zapisanym przed wersją 4.0.0 wszystkie blokady są włączone, a w każdym dokumencie zapisanym przed wersją 4.2.0 zablokowane jest ustawienie Name View.
Gdy ustawienie Viewport jest odblokowane, przewinięcie lub zmiana powiększenia zmienia value, gdy odblokowane jest ustawienie Canvas Type, to samo dotyczy otwarcia innej karty edytora, a gdy odblokowane jest ustawienie Name View, to samo dotyczy przełączenia Widoku nazw w edytorze, który nie jest tylko do odczytu.
Włączenie lub wyłączenie blokady również zmienia value.
Od wersji 4.0.0 pole changed porównuje postać zapisu, która nie zawiera ani usuniętych encji, ani kolejności warstw.
Dlatego tabela dodana i ponownie usunięta w obrębie jednego zdarzenia change, zmiana, która trafia na encję usuniętą przez innego współpracownika, oraz przekazane wczytanie, które zmienia tylko kolejność warstw, również dają pole changed ustawione na false.
Od wersji 4.2.0 to samo dotyczy wiersza dodanego do arkusza karty Słownik i pozostawionego bez zawartości, ponieważ postać zapisu pomija wiersz, który niczego nie zawiera.
Pole changed nigdy nie wynika z porównania z zapisanym plikiem, który już po wczytaniu może różnić się od value: tak jest w przypadku pliku zapisanego przez wcześniejszą wersję, w tym pliku v2, a także pliku zaczynającego się od znacznika kolejności bajtów i pliku edytowanego ręcznie.
Od wersji 4.2.0 dotyczy to też pliku zapisanego przez wersję 4.0.0 lub 4.1.0, ponieważ value pomija puste pola tekstowe jego encji oraz puste listy doc i kolekcje, które zawiera taki plik.
Porównanie bajtów z takim plikiem uznałoby za zmianę nawet przewinięcie, które blokada pomija.
Pierwsze zdarzenie change z polem changed ustawionym na true zwraca taki plik w postaci zapisu, więc zapisanie tej wartości jednorazowo przepisuje plik.
Plik zapisany w tej wersji nie różni się, niezależnie od tego, gdzie go zapisano, co wyjaśnia sekcja toWidth.
Jeśli wywołanie setInitialValue nastąpi, gdy zdarzenie change jeszcze oczekuje, a przed jego terminem nic nie zostanie przekazane, to zdarzenie change mimo to nadejdzie z wczytaną wartością value i polem changed ustawionym na false.
dispatch, dispatchSync
Stosuje w magazynie replicationStore zmiany pochodzące ze zdalnego edytora.
replicationStore.dispatch(actions); // async
replicationStore.dispatchSync(actions); // sync
Metoda dispatch odkłada zastosowanie pakietu do mikrozadania, a dispatchSync stosuje pakiet od razu.
Strumień współdzielonego magazynu możesz przekazać bez filtrowania.
Obie metody zachowują tylko akcje takiego rodzaju, który może zmienić dokument, oraz dwie akcje opisane na końcu tej sekcji, pomijając pozostałe, więc informacje o obecności przesyłane w sesji wspólnej edycji – kursor myszy, fokus, zaznaczenie i ramka przeciągania każdego użytkownika – przechodzą przez nie bez żadnego skutku.
Od wersji 3.10.0 zachowywane akcje obejmują relationship.changeOnDelete i relationship.changeOnUpdate, a akcja relationship.add zawiera pola onDelete i onUpdate.
Magazyn z wcześniejszej wersji pomija te akcje i ignoruje te pola, więc traci akcje ON DELETE i ON UPDATE relacji.
Od wersji 4.0.0 zachowywane akcje obejmują też table.changeGroup, siedem z ośmiu akcji tableGroup (tableGroup.add, tableGroup.move, tableGroup.moveTo, tableGroup.remove, tableGroup.resize, tableGroup.changeName i tableGroup.changeColor, czyli wszystkie oprócz zmiany kolejności warstw tableGroup.changeZIndex), relationship.changeColumns, settings.changeLockSettings i settings.changeDDLScript.
Akcja settings.changeRelationshipOptimization już nie istnieje, więc obie metody ją pomijają.
Magazyn z wcześniejszej wersji pomija nowe akcje, więc traci grupy tabel, blokady, skrypty karty Schemat SQL i kolumny, które okno dialogowe Mapuj kolumny przypisuje istniejącej relacji.
Uruchamiaj replikę w tej samej wersji co edytory lub w nowszej.
Wersja 4.1.0 nie dodaje żadnego typu akcji i pozostawia @dineug/erd-editor/engine.js bez zmian, więc replika w wersji 4.0.0 zachowuje każdą zmianę wysyłaną przez edytor w wersji 4.1.0, tak samo jak replika w wersji 4.1.0.
Od wersji 4.1.0 przyciski Replace i Replace All w funkcji Znajdź i zamień zmieniają też nazwy indeksów i grup tabel za pomocą akcji index.changeName i tableGroup.changeName, które replika w wersji 4.0.0 już zachowuje.
Własny stan panelu Eksplorator nigdy nie jest wysyłany, a przełączenie karty lub przewinięcie wywołane przez ten panel dociera tak samo jak każde inne przełączenie karty lub przewinięcie; zobacz stronę Wspólna edycja.
Od wersji 4.2.0 zachowywane akcje obejmują też table.changeLogicalName, table.changeNameDerived, column.changeLogicalName, column.changeDomain, column.changeNameDerived, settings.changeNameViewMode oraz dictionary.add, dictionary.update i dictionary.remove, które przenoszą każdą edycję, sortowanie i import CSV w arkuszach karty Słownik.
Z przełączeń Widoku nazw replika stosuje tylko te, które przy odblokowanym ustawieniu Name View wykonuje edytor, który nie jest tylko do odczytu, a pozostałe pomija (zobacz sekcję on@change).
Magazyn z wcześniejszej wersji pomija wszystkie te akcje, więc traci nazwy logiczne, powiązania z domenami, informację, czy każda nazwa pochodzi ze słowników, słowa, terminy i domeny oraz Widok nazw.
Edytor w wersji starszej niż 4.2.0 uczestniczący w sesji może nadal odebrać część tych danych replice w wersji 4.2.0.
Operacja Import w formacie Schemat SQL, GraphQL, DBML lub AML wykonana w tym edytorze, choć już nie operacja Import and Add, opróżnia słowa, terminy i domeny repliki.
Cofnięcie przez niego wczytania, operacji Import lub wywołania clear() wczytuje do repliki jego własną kopię dokumentu, bez nazw logicznych, powiązań z domenami i słowników; zobacz sekcję Mieszanie wersji.
Punkt wejścia @dineug/erd-editor/engine.js eksportuje te same elementy createReplicationStore, ReplicationStore i ReplicationChange co wcześniej, a funkcja createReplicationStore przyjmuje ten sam kontekst.
Wersja 5.1.0 nie dodaje żadnego typu akcji i nie zmienia żadnego eksportu @dineug/erd-editor/engine.js, więc replika w wersji 4.2.0 lub nowszej nadal zachowuje każdą zmianę wysyłaną przez edytor w wersji 5.1.0.
Od wersji 5.1.0 replika uzgadnia edycje wykonane w tej samej chwili tak jak edytory w wersji 5.1.0; zobacz sekcję Równoczesne edycje.
Przechowuje wersję położenia tabeli, położenia i rozmiaru notatki oraz grupy tabel, a także położenia widoku i poziomu powiększenia.
Edytor w wersji 5.1.0 wysyła przeciągnięcie, przesunięcie widoku lub zmianę powiększenia jako miejsce, w którym się kończą, za pomocą akcji table.moveTo, memo.moveTo, tableGroup.moveTo, settings.scrollTo i settings.changeZoomLevel, a replika przyjmuje każdą z nich, podobnie jak każdą akcję memo.resize i tableGroup.resize, tylko wtedy, gdy jej wersja nie jest niższa od przechowywanej.
Dlatego gdy dwa takie edytory w tej samej chwili przesuwają jedną tabelę, notatkę lub grupę tabel albo zmieniają jej rozmiar, replika zapisuje ją w punkcie i o rozmiarze, które pokazują wszystkie z nich, niezależnie od kolejności, w jakiej je odbiera, a przeciągnięcie, przesunięcie widoku lub zmiana powiększenia dostarczone przez transport dwa razy nie przesuwa niczego dwa razy.
Gdy ustawienie Viewport jest odblokowane, replika zapisuje położenie widoku i poziom powiększenia, każde z zapisu o największej wersji, czyli w miejscu, w którym stał edytor, który go wykonał.
Zmiana powiększenia zmienia też położenie widoku, więc przesunięcie widoku i zmiana powiększenia wykonane przez dwa edytory w tej samej chwili mogą zostać zapisane jako położenie widoku jednego edytora z poziomem powiększenia drugiego.
Przed wersją 5.1.0 replika dodawała kroki przesuwania i powiększania wszystkich edytorów do jednego widoku.
Odległości, które edytor w wersji starszej niż 5.1.0 wysyła dla przeciągnięcia, przesunięcia widoku lub zmiany powiększenia (table.move, memo.move, tableGroup.move, settings.streamScrollTo i settings.streamZoomLevel), są nadal dodawane do tego, co przechowuje replika, poza wersjami.
Zmiana koloru nadal dociera bez wersji: replika, podobnie jak każdy edytor, oznacza ją własną wersją i zachowuje kolor odebrany jako ostatni, więc dwie zmiany koloru jednej tabeli, notatki lub grupy tabel wykonane w tej samej chwili mogą zostać zapisane inaczej, niż pokazuje edytor.
Replika w wersji starszej niż 5.1.0 stosuje punkty i rozmiary w kolejności ich nadejścia, więc może zapisać tabelę w innym miejscu, niż pokazują ją edytory w wersji 5.1.0.
Aby edycje wykonane w tej samej chwili kończyły tak samo, poza wyjątkami wymienionymi w sekcji Równoczesne edycje, utrzymuj wszystkie edytory w sesji oraz replikę w wersji 5.1.0 lub nowszej.
Od wersji 5.1.0 edytor wysyła zmianę języka Generatora kodu, stylu nazw lub typu cudzysłowu tylko wtedy, gdy blokada tego ustawienia jest wyłączona, z oznaczeniem shared: true w ładunku, a replika stosuje każdą tak oznaczoną zmianę, tak jak edytory; zobacz stronę Wspólna edycja.
Replika stosuje zmianę bez oznaczenia, którą edytor w wersji starszej niż 5.1.0 wysyła niezależnie od blokady, tylko wtedy, gdy to ustawienie jest po jej stronie odblokowane, a gdy jest zablokowane, pomija ją (zobacz sekcję on@change).
Od wersji 4.0.0 obie metody stosują też akcję editor.mergeLWW, która przenosi rejestry współpracy wysyłane przez edytor w odpowiedzi na dołączenie innego edytora do sesji, więc replika uzgadnia równoczesne zmiany tak samo jak edytory.
Nie zmienia ani jednego bajtu value i nie wywołuje zdarzenia change.
Akcja settings.changeIgnoreSaveSettings, którą edytor wydany przed wersją 4.0.0 może nadal wysyłać, jest zachowywana, ale niczego nie zmienia: wywołuje zdarzenie change z polem changed ustawionym na false.
destroy
Całkowicie niszczy instancję replicationStore.
replicationStore.destroy();
Następnie magazyn przestaje emitować zdarzenie change i ignoruje kolejne przekazywane akcje.
Dokument pozostaje zamrożony w ostatniej wartości, a błąd nie jest zgłaszany.
Aby zacząć od nowa, utwórz nowy magazyn.