Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jtbennett/2012016 to your computer and use it in GitHub Desktop.
Save jtbennett/2012016 to your computer and use it in GitHub Desktop.
RavenDB LastInWinsReplicationConflictResolver
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]);
}
}
}
}
@leethomascook
Copy link

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.Buffer1..ctor(IEnumerable1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.<>c__DisplayClass1.b__0()
at System.Lazy1.CreateValue() at System.Lazy1.LazyInitValue()
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.RaiseChangedEvent(Lazy1 addedDefinitions, Lazy1 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()

@jtbennett
Copy link
Author

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).

@afifmohammed
Copy link

This does not work with 2261. The bundles nuget package only goes upto 1.0.992.

@johnculviner
Copy link

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