public override void OnPut(string key, JObject document, JObject metadata, TransactionInformation transactionInformation) { if (ReplicationContext.IsInReplicationContext) { return; } using (ReplicationContext.Enter()) { metadata.Remove(ReplicationConstants.RavenReplicationConflict);// you can't put conflicts var oldVersion = Database.Get(key, transactionInformation); if (oldVersion == null) { return; } if (oldVersion.Metadata[ReplicationConstants.RavenReplicationConflict] == null) { return; } // this is a conflict document, holding document keys in the // values of the properties foreach (var prop in oldVersion.DataAsJson.Value <JArray>("Conflicts")) { Database.Delete(prop.Value <string>(), null, transactionInformation); } } }
public override void Respond(IHttpContext context) { var src = context.Request.QueryString["from"]; if (string.IsNullOrEmpty(src)) { context.SetStatusToBadRequest(); return; } while (src.EndsWith("/")) { src = src.Substring(0, src.Length - 1);// remove last /, because that has special meaning for Raven } if (string.IsNullOrEmpty(src)) { context.SetStatusToBadRequest(); return; } using (ReplicationContext.Enter()) { var document = Database.Get(ReplicationConstants.RavenReplicationSourcesBasePath + "/" + src, null); if (document == null) { log.DebugFormat("Got replication last etag request from {0}: [{1}]", src, Guid.Empty); context.WriteJson(new { Etag = Guid.Empty }); } else { var sourceReplicationInformation = document.DataAsJson.JsonDeserialization <SourceReplicationInformation>(); log.DebugFormat("Got replication last etag request from {0}: [{1}]", src, sourceReplicationInformation.LastEtag); context.WriteJson(new { Etag = sourceReplicationInformation.LastEtag }); } } }
public override void Respond(IHttpContext context) { var src = context.Request.QueryString["from"]; if (string.IsNullOrEmpty(src)) { context.SetStatusToBadRequest(); return; } while (src.EndsWith("/")) { src = src.Substring(0, src.Length - 1);// remove last /, because that has special meaning for Raven } if (string.IsNullOrEmpty(src)) { context.SetStatusToBadRequest(); return; } var array = context.ReadJsonArray(); using (ReplicationContext.Enter()) { Database.TransactionalStorage.Batch(actions => { string lastEtag = Guid.Empty.ToString(); foreach (JObject document in array) { var metadata = document.Value <JObject>("@metadata"); if (metadata[ReplicationConstants.RavenReplicationSource] == null) { // not sure why, old document from when the user didn't have replciation // that we suddenly decided to replicate, choose the source for that metadata[ReplicationConstants.RavenReplicationSource] = JToken.FromObject(src); } lastEtag = metadata.Value <string>("@etag"); var id = metadata.Value <string>("@id"); document.Remove("@metadata"); ReplicateDocument(actions, id, metadata, document, src); } var replicationDocKey = ReplicationConstants.RavenReplicationSourcesBasePath + "/" + src; var replicationDocument = Database.Get(replicationDocKey, null); var lastAttachmentId = Guid.Empty; if (replicationDocument != null) { lastAttachmentId = replicationDocument.DataAsJson.JsonDeserialization <SourceReplicationInformation>(). LastAttachmentEtag; } Database.Put(replicationDocKey, null, JObject.FromObject(new SourceReplicationInformation { LastDocumentEtag = new Guid(lastEtag), LastAttachmentEtag = lastAttachmentId }), new JObject(), null); }); } }
private void Execute() { var context = docDb.WorkContext; while (context.DoWork) { try { using (ReplicationContext.Enter()) { var destinations = GetReplicationDestinations(); if (destinations.Length == 0) { WarnIfNoReplicationTargetsWereFound(); } else { var currentReplicationAttempts = Interlocked.Increment(ref replicationAttempts); var destinationForReplication = destinations .Where(dest => IsNotFailing(dest, currentReplicationAttempts)); foreach (var dest in destinationForReplication) { var destination = dest; var holder = activeReplicationTasks.GetOrAdd(destination, new IntHolder()); if (Thread.VolatileRead(ref holder.Value) == 1) { continue; } Thread.VolatileWrite(ref holder.Value, 1); Task.Factory.StartNew(() => ReplicateTo(destination), TaskCreationOptions.LongRunning) .ContinueWith(completedTask => { if (completedTask.Result) // force re-evaluation of replication again { docDb.WorkContext.NotifyAboutWork(); } }); } } } } catch (Exception e) { log.Error("Failed to perform replication", e); } context.WaitForWork(TimeSpan.FromMinutes(1), ref workCounter); } }
private bool ReplicateTo(string destination) { try { using (ReplicationContext.Enter()) { SourceReplicationInformation sourceReplicationInformation; try { sourceReplicationInformation = GetLastReplicatedEtagFrom(destination); if (sourceReplicationInformation == null) { return(false); } } catch (Exception e) { log.Warn("Failed to replicate to: " + destination, e); return(false); } bool?replicated = null; switch (ReplicateDocuments(destination, sourceReplicationInformation)) { case true: replicated = true; break; case false: return(false); } switch (ReplicateAttachments(destination, sourceReplicationInformation)) { case true: replicated = true; break; case false: return(false); } return(replicated ?? false); } } finally { var holder = activeReplicationTasks.GetOrAdd(destination, new IntHolder()); Thread.VolatileWrite(ref holder.Value, 0); } }
private void ReplicateTo(string destination) { try { using (ReplicationContext.Enter()) { JArray jsonDocuments; try { var etag = GetLastReplicatedEtagFrom(destination); if (etag == null) { return; } jsonDocuments = GetJsonDocuments(etag.Value); if (jsonDocuments == null || jsonDocuments.Count == 0) { return; } } catch (Exception e) { log.Warn("Failed to replicate to: " + destination, e); return; } if (TryReplicatingData(destination, jsonDocuments) == false)// failed to replicate, start error handling strategy { if (IsFirstFailue(destination)) { log.InfoFormat( "This is the first failure for {0}, assuming transinet failure and trying again", destination); if (TryReplicatingData(destination, jsonDocuments))// second failure! { return; } } IncrementFailureCount(destination); } } } finally { var holder = activeReplicationTasks.GetOrAdd(destination, new IntHolder()); Thread.VolatileWrite(ref holder.Value, 0); } }