public ResolveConflictOnReplicationConfigurationChange(ReplicationLoader replicationLoader, Logger log) { _replicationLoader = replicationLoader ?? throw new ArgumentNullException($"{nameof(ResolveConflictOnReplicationConfigurationChange)} must have replicationLoader instance"); _database = _replicationLoader.Database; _log = log; }
public OutgoingReplicationHandler(ReplicationLoader parent, DocumentDatabase database, ReplicationNode node, bool external, TcpConnectionInfo connectionInfo) { _parent = parent; _database = database; Destination = node; _external = external; _log = LoggingSource.Instance.GetLogger <OutgoingReplicationHandler>(_database.Name); _connectionInfo = connectionInfo; _database.Changes.OnDocumentChange += OnDocumentChange; _cts = CancellationTokenSource.CreateLinkedTokenSource(_database.DatabaseShutdown); }
private bool ShouldSkip(ReplicationBatchItem item, OutgoingReplicationStatsScope stats, SkippedReplicationItemsInfo skippedReplicationItemsInfo) { if (ValidatorSaysToSkip(_pathsToSend) || ValidatorSaysToSkip(_destinationAcceptablePaths)) { return(true); } if (_shouldSkipSendingTombstones && ReplicationLoader.IsOfTypePreventDeletions(item)) { return(true); } switch (item) { case DocumentReplicationItem doc: if (doc.Flags.Contain(DocumentFlags.Artificial)) { stats.RecordArtificialDocumentSkip(); skippedReplicationItemsInfo.Update(item, isArtificial: true); return(true); } if (doc.Flags.Contain(DocumentFlags.Revision) || doc.Flags.Contain(DocumentFlags.DeleteRevision)) { // we let pass all the conflicted/resolved revisions, since we keep them with their original change vector which might be `AlreadyMerged` at the destination. if (doc.Flags.Contain(DocumentFlags.Conflicted) || doc.Flags.Contain(DocumentFlags.Resolved) || (doc.Flags.Contain(DocumentFlags.FromClusterTransaction))) { return(false); } } break; case AttachmentReplicationItem _: if (MissingAttachmentsInLastBatch) { return(false); } break; } // destination already has it if (_parent._database.DocumentsStorage.GetConflictStatus(item.ChangeVector, _parent.LastAcceptedChangeVector) == ConflictStatus.AlreadyMerged) { stats.RecordChangeVectorSkip(); skippedReplicationItemsInfo.Update(item); return(true); } return(false); bool ValidatorSaysToSkip(AllowedPathsValidator validator) { if (validator == null) { return(false); } if (validator.ShouldAllow(item)) { return(false); } stats.RecordArtificialDocumentSkip(); skippedReplicationItemsInfo.Update(item); if (_log.IsInfoEnabled) { string key = validator.GetItemInformation(item); _log.Info($"Will skip sending {key} ({item.Type}) because it was not allowed according to the incoming ."); } return(true); } }