示例#1
0
 public ResolveConflictOnReplicationConfigurationChange(ReplicationLoader replicationLoader, Logger log)
 {
     _replicationLoader = replicationLoader ??
                          throw new ArgumentNullException($"{nameof(ResolveConflictOnReplicationConfigurationChange)} must have replicationLoader instance");
     _database = _replicationLoader.Database;
     _log      = log;
 }
示例#2
0
 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);
 }
示例#3
0
        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);
            }
        }