Created
March 10, 2012 16:41
-
-
Save jtbennett/2012016 to your computer and use it in GitHub Desktop.
RavenDB LastInWinsReplicationConflictResolver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using NLog; | |
using Raven.Abstractions.Data; | |
using Raven.Bundles.Replication; | |
using Raven.Bundles.Replication.Plugins; | |
using Raven.Json.Linq; | |
namespace MyRavenReplicationBundle | |
{ | |
public class LastInWinsReplicationConflictResolver | |
: AbstractDocumentReplicationConflictResolver | |
{ | |
private readonly Logger log = LogManager.GetCurrentClassLogger(); | |
public override bool TryResolve( | |
string id, | |
RavenJObject metadata, | |
RavenJObject document, | |
JsonDocument existingDoc) | |
{ | |
if (this.ExistingDocShouldWin(metadata, existingDoc)) | |
{ | |
this.ReplaceValues(metadata, existingDoc.Metadata); | |
this.ReplaceValues(document, existingDoc.DataAsJson); | |
log.Debug("Replication conflict for '{0}' resolved by choosing existing document.", id); | |
} | |
else | |
{ | |
log.Debug("Replication conflict for '{0}' resolved by choosing inbound document.", id); | |
} | |
return true; | |
} | |
private bool ExistingDocShouldWin(RavenJObject newMetadata, JsonDocument existingDoc) | |
{ | |
if (existingDoc == null || | |
this.ExistingDocHasConflict(existingDoc) || | |
this.ExistingDocIsOlder(newMetadata, existingDoc)) | |
{ | |
return false; | |
} | |
return true; | |
} | |
private bool ExistingDocHasConflict(JsonDocument existingDoc) | |
{ | |
return existingDoc.Metadata[ReplicationConstants.RavenReplicationConflict] != null; | |
} | |
private bool ExistingDocIsOlder(RavenJObject newMetadata, JsonDocument existingDoc) | |
{ | |
var newLastModified = this.GetLastModified(newMetadata); | |
if (!existingDoc.LastModified.HasValue || | |
newLastModified.HasValue && | |
existingDoc.LastModified <= newLastModified) | |
{ | |
return true; | |
} | |
return false; | |
} | |
private DateTime? GetLastModified(RavenJObject metadata) | |
{ | |
var lastModified = metadata[Constants.LastModified]; | |
return (lastModified == null) ? | |
new DateTime?() : | |
lastModified.Value<DateTime?>(); | |
} | |
private void ReplaceValues(RavenJObject target, RavenJObject source) | |
{ | |
var targetKeys = target.Keys.ToArray(); | |
foreach (var key in targetKeys) | |
{ | |
target.Remove(key); | |
} | |
foreach (var key in source.Keys) | |
{ | |
target.Add(key, source[key]); | |
} | |
} | |
} | |
} |
This still works just fine, ignore the comment above which unfortunately discouraged me from even trying!
Just change "ReplicationConstants." to "Constants." and you should be good.
All you need to do is create a class library assembly "project" and import the "RavenDB.Database" nuget package and create the above class in the project. Compile and then add the resulting DLL to {RavenInstallDirectory}\Plugins and bounce the server. Quite impressed with the flexibility here!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This does not work with 2261. The bundles nuget package only goes upto 1.0.992.