Rozwiązanie, nad którym teraz pracuję, które jak dotąd działa dobrze, realizuje projekt, który zaproponowałem w pytaniu
W tym miejscu podzielę się szczegółami mojej implementacji
Do tworzenia delt i używania do rekonstrukcji pełnego tekstu używam fantastycznego biblioteka google-diff-match-patch . Możesz zapoznać się z dokumentacją API niezależną od implementacji aby lepiej zrozumieć poniższe przykłady kodu, choć i tak są dość czytelne.
poprawka-dopasowania-róż-google ma implementacje Java i JS, więc mogę go użyć do obliczenia delt z Javą na serwerze. Zdecydowałem się przekonwertować każdą deltę na ciąg znaków, aby można ją było łatwo przechowywać w bazie danych i łatwo wykorzystać w bibliotece JS na kliencie. Więcej na ten temat poniżej.
public String getBackwardsDelta(String editedBlogPost, String existingBlogPost) {
diff_match_patch dmp = new diff_match_patch();
LinkedList<diff_match_patch.Patch> patches =
dmp.patch_make(editedBlogPost, existingBlogPost);
return dmp.patch_toText(patches);
}
Uwaga coś, co zajęło mi trochę czasu, to jak ściągnąć oficjalną wersję google-diff-match-patch za pomocą mavena. Nie znajduje się w centralnym repozytorium maven, ale we własnym repozytorium na googlecode.com. Warto zauważyć, że niektórzy ludzie rozwidlali go i umieścili swoje rozwidlone wersje w maven central, ale jeśli naprawdę chcesz oficjalną wersję, możesz uzyskać, dodając repozytorium i zależność w swoim pom.xml
w następujący sposób
<repository>
<id>google-diff-patch-match</id>
<name>google-diff-patch-match</name>
<url>https://google-diff-match-patch.googlecode.com/svn/trunk/maven/</url>
</repository>
<dependency>
<groupId>diff_match_patch</groupId>
<artifactId>diff_match_patch</artifactId>
<version>current</version>
</dependency>
Na potrzeby interfejsu przekazuję pełny tekst najnowszego posta na blogu, wraz z łańcuchem delt cofniętych w czasie, reprezentujących każdą edycję, a następnie rekonstruuję pełny tekst każdej wersji w przeglądarce w JS.
Aby pobrać bibliotekę, używam npm + browserify. Biblioteka jest dostępna na npm jako diff-match-patch . Wersja 1.0.0 jest jedyną wersją.
getTextFromDelta: function(originalText, delta) {
var DMP = require('diff-match-patch'); // get the constructor function
var dmp = new DMP();
var patches = dmp.patch_fromText(delta);
return dmp.patch_apply(patches, originalText)[0];
}
I to wszystko, działa fantastycznie.
Jeśli chodzi o przechowywanie zmian w postach na blogu, po prostu używam tabeli BLOG_POST_EDITS
gdzie przechowuję identyfikator posta na blogu, znacznik czasu, kiedy dokonano edycji (którego później używam do prawidłowego uporządkowania edycji, aby utworzyć łańcuch podczas rekonstrukcji wersji pełnotekstowych na kliencie) oraz deltę wstecz między bieżącymi wersjami na żywo wpis na blogu w BLOG_POST
tabeli i przychodzącej edytowanej wersji posta na blogu.
Zdecydowałem się przechowywać „łańcuch” delt, ponieważ dobrze pasuje do mojego przypadku użycia i jest prostszy na końcu kodu serwera. Oznacza to, że aby zrekonstruować wersję M z N, muszę wysłać klientowi łańcuch delt N-(M-1) z powrotem z pełnego tekstu posta na blogu do wersji M. Ale w moim przypadku użycia zdarza mi się i tak chcesz wysłać cały łańcuch za każdym razem, więc to jest w porządku.
Aby uzyskać nieco lepszą wydajność przesyłania przez sieć w przypadku żądania określonych wersji, wszystkie delty można przeliczyć z nowej edytowanej wersji posta na blogu z powrotem do każdej (przywróconej) wersji za każdym razem, gdy dokonywana jest zmiana, ale oznaczałoby to więcej pracy i złożoności w serwer.