-
-
Save jtbennett/2012016 to your computer and use it in GitHub Desktop.
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]); | |
} | |
} | |
} | |
} |
Had some issues using this... I assume you just drop the DLL you create in to your plugins directory on your server? This is on build 960.
I get this exception when restarting the service:
RavenDB service failed to start because of an error
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.Assembly.GetTypes()
at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_InnerCatalog()
at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_Parts()
at lambda_method(Closure , ComposablePartCatalog )
at System.Linq.Enumerable.d__142.MoveNext() at System.Linq.Buffer
1..ctor(IEnumerable1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source)
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.<>c__DisplayClass1.b__0()
at System.Lazy1.CreateValue() at System.Lazy
1.LazyInitValue()
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.RaiseChangedEvent(Lazy1 addedDefinitions, Lazy
1 removedDefinitions)
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.Add(ComposablePartCatalog item)
at Raven.Database.Config.InMemoryRavenConfiguration.set_PluginsDirectory(String value) in c:\Builds\RavenDB-Stable\Raven.Database\Config\InMemoryRavenConfiguration.cs:line 607
at Raven.Database.Config.InMemoryRavenConfiguration.Initialize() in c:\Builds\RavenDB-Stable\Raven.Database\Config\InMemoryRavenConfiguration.cs:line 188
at Raven.Database.Config.RavenConfiguration.LoadConfigurationAndInitialize(IEnumerable`1 values) in c:\Builds\RavenDB-Stable\Raven.Database\Config\RavenConfiguration.cs:line 28
at Raven.Database.Config.RavenConfiguration..ctor() in c:\Builds\RavenDB-Stable\Raven.Database\Config\RavenConfiguration.cs:line 17
at Raven.Server.RavenService.b__0()
Sorry I didn't see this until now. I've seen that exception in cases where I had either the wrong DLLs in the Plugins folder, or DLLs with references to different versions of Raven that were in the bin. You need to have both this DLL and the Raven.Bundles.Replication.dll in the Plugins folder. You don't want any other Raven DLLs in Plugins (like Raven.Abstractions).
This does not work with 2261. The bundles nuget package only goes upto 1.0.992.
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!
See the related blog post at http://development.msnbc.msn.com/_news/2012/03/10/10634272-customizing-ravendb-a-simple-ravendb-server-bundle-for-replication-conflict-handling