Решение, върху което работя в момента, което работи добре досега, изпълнява дизайна, който предложих във въпроса
Ще споделя спецификата на моето внедряване тук
За създаване на делта и използване на за възстановяване на пълния текст използвам фантастичния библиотека google-diff-match-patch . Можете да прочетете агностичната документация за API за по-добро разбиране на примерите за код по-долу, въпреки че така или иначе е доста четим.
google-diff-match-patch има реализации на Java и JS, така че мога да го използвам за изчисляване на делтите с Java на сървъра. Избрах да конвертирам всяка делта в низ, така че да може лесно да се съхранява в базата данни и лесно да се използва от JS библиотеката на клиента. Повече за това по-долу.
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);
}
N.B. нещо, което ми отне известно време да разбера, беше как да сваля официалната компилация на google-diff-match-patch използвайки maven. Не е в централното репо на maven, а в тяхното собствено репо на googlecode.com. Само да отбележа, че някои хора са го разклонили и са поставили своите разклонени версии в maven central, но ако наистина искате официалната версия, можете да получите, като добавите репото и зависимостта във вашия pom.xml
както следва
<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>
За предния край предавам най-новата публикация в блога пълен текст, заедно с верига от делти, връщащи се назад във времето, представляващи всяка редакция, и след това реконструирам пълния текст на всяка версия в браузъра в JS.
За да получа библиотеката, използвам npm + browserify. Библиотеката е достъпна на npm като diff-match-patch . Версия 1.0.0 е единствената версия.
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];
}
И това е всичко, работи фантастично.
По отношение на съхраняването на редакциите на публикациите в блога, аз просто използвам таблица BLOG_POST_EDITS
където съхранявам идентификационния номер на публикацията в блога, клеймо за времето, когато е направена редакцията (което по-късно използвам, за да подредя правилно редакциите, за да направя веригата, когато реконструирам пълнотекстовите версии на клиента) и обратната делта между текущия жив публикация в блога в BLOG_POST
таблица и входящата редактирана версия на публикацията в блога.
Избрах да съхранявам „верига“ от делта, защото отговаря добре на моя случай на употреба и е по-проста в края на сървърния код. Това наистина означава, че за да реконструирам версия M на N, трябва да изпратя на клиента верига от N-(M-1) делта обратно от публикацията в блога на живо с пълен текст до версия M. Но в моя случай на употреба се случва да искам да изпращам цялата верига всеки път, така че това е добре.
За малко по-добра ефективност по кабела за заявяване на конкретни версии, всички делти могат да бъдат преизчислени от новата редактирана версия на публикация в блога обратно към всяка (възстановена) версия всеки път, когато се прави редакция, но това би означавало повече работа и сложност на сървър.