En lösning jag jobbar på just nu, som fungerar bra hittills, implementerar designen jag föreslog i frågan
Jag kommer att dela med mig av detaljerna för min implementering här
För att skapa delta och använda för att rekonstruera hela texten använder jag den fantastiska google-diff-match-patch library . Du kan läsa den agnostiska implementeringen API-dokumentationen för att bättre förstå kodexemplen nedan, även om det är ganska läsbart ändå.
google-diff-match-patch har Java- och JS-implementationer så jag kan använda den för att beräkna deltas med Java på servern. Jag valde att konvertera varje delta till en sträng båda så att det enkelt kan lagras i databasen och enkelt konsumeras av JS-biblioteket på klienten. Mer om detta nedan.
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);
}
Obs. något det tog mig ett tag att ta reda på var hur man drar ner den officiella versionen av google-diff-match-patch använder maven. Det finns inte i Mavens centrala repo, utan på deras eget repo på googlecode.com. Bara för att notera, vissa människor har klaffat det och lagt sina gafflade versioner i maven central, men om du verkligen vill ha den officiella versionen kan du få genom att lägga till repo och beroende i din pom.xml
enligt följande
<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>
För gränssnittet skickar jag det senaste blogginlägget i fulltext, tillsammans med en kedja av deltas som går bakåt i tiden som representerar varje redigering, och rekonstruerar sedan hela texten för varje version i webbläsaren i JS.
För att få biblioteket använder jag npm + browserify. Biblioteket är tillgängligt på npm som diff-match-patch . Version 1.0.0 är den enda versionen.
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];
}
Och det är det, det fungerar fantastiskt.
När det gäller att lagra redigeringarna av blogginläggen använder jag bara en tabell BLOG_POST_EDITS
där jag lagrar blogginläggets id, en tidsstämpel för när redigeringen gjordes (som jag senare använder för att beställa redigeringarna korrekt för att göra kedjan när jag rekonstruerar fulltextversionerna på klienten), och bakåtdeltatet mellan den aktuella live blogginlägg i BLOG_POST
tabell och den inkommande redigerade versionen av blogginlägget.
Jag valde att lagra en "kedja" av deltas eftersom det passar mitt användningsfall bra och är enklare på serverkoden. Det betyder att för att kunna rekonstruera version M av N måste jag skicka tillbaka en kedja av N-(M-1) delta till klienten från liveblogginläggets fulltext till version M. Men i mitt användningsfall råkar jag vill skicka hela kedjan varje gång, i alla fall, så det här är bra.
För något bättre över-the-wire effektivitet för att begära specifika versioner, kan alla deltas räknas om från den nya redigerade blogginläggsversionen tillbaka till varje (återställd) version varje gång en redigering görs, men detta skulle innebära mer arbete och komplexitet på server.