private string FetchTargetServerUrl(ReplicationDestination replicationDestination)
        {
            var url = $"{replicationDestination.Url}/debug/config";

            try
            {
                var replicationStrategy       = ReplicationTask.GetConnectionOptions(replicationDestination, database);
                var request                   = requestFactory.Create(url, HttpMethods.Get, replicationStrategy.ConnectionStringOptions);
                var ravenConfig               = request.ExecuteRequest <RavenJObject>();
                var serverUrlFromTargetConfig = ravenConfig.Value <string>("ServerUrl");

                // replace host name with target hostname
                return(new UriBuilder(replicationDestination.Url)
                {
                    Host = new Uri(serverUrlFromTargetConfig).Host
                }.Uri.ToString());
            }
            catch (Exception e)
            {
                if (replicationDestination.Url.EndsWith("/"))
                {
                    return(replicationDestination.Url);
                }

                return(replicationDestination.Url + "/");
            }
        }
        public DocumentCount Calculate(ServerInfo serverInfo)
        {
            var replicationDocument = GetReplicationDocument();

            if (serverInfo.SourceId != DatabaseId)
            {
                return(GetDocumentsLeftCountFromAnotherSourceServer(replicationDocument, serverInfo));
            }

            var replicationDestination = replicationDocument
                                         .Destinations
                                         .FirstOrDefault(x => FetchTargetServerUrl(x).Equals(serverInfo.DestinationUrl, StringComparison.CurrentCultureIgnoreCase) &&
                                                         x.Database.Equals(serverInfo.DatabaseName, StringComparison.CurrentCultureIgnoreCase));

            if (replicationDestination == null)
            {
                throw new InvalidOperationException($"Couldn't find replication destination for url: {serverInfo.DestinationUrl} and database: {serverInfo.DatabaseName}");
            }

            var replicationStrategy = ReplicationTask.GetConnectionOptions(replicationDestination, database);

            if (replicationStrategy.IsETL == false)
            {
                return(GetDocumentsLeftCount(replicationStrategy, serverInfo.DestinationUrl, serverInfo.DatabaseName));
            }

            return(GetDocumentsLeftCountForEtl(replicationStrategy, serverInfo.DestinationUrl, serverInfo.DatabaseName));
        }
        private DocumentCount DocumentsLeftCountFromAnotherSourceServer(ServerInfo serverInfo,
                                                                        ReplicationDestination.ReplicationDestinationWithConfigurationOrigin replicationDestination)
        {
            var replicationStrategy = ReplicationTask.GetConnectionOptions(replicationDestination, database);
            var url     = $"{replicationStrategy.ConnectionStringOptions.Url}/admin/replication/docs-left-to-replicate";
            var request = requestFactory.Create(url, HttpMethods.Post, replicationStrategy.ConnectionStringOptions);

            request.Write(RavenJObject.FromObject(serverInfo));

            var documentsLeftCount = request.ExecuteRequest <DocumentCount>();

            return(documentsLeftCount);
        }
Example #4
0
        private ReplicationTopologyDestinationNode HandleDestination(ReplicationDestination replicationDestination)
        {
            var destination = ReplicationTask.GetConnectionOptions(replicationDestination, database);

            if (replicationDestination.Disabled)
            {
                return(ReplicationTopologyDestinationNode.Disabled(destination.ConnectionStringOptions.Url, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior));
            }

            if (from.Contains(destination.ConnectionStringOptions.Url))
            {
                var state = CheckDestinationConnectionState(destination);
                switch (state)
                {
                case ReplicatonNodeState.Online:
                    return(ReplicationTopologyDestinationNode.Online(destination.ConnectionStringOptions.Url, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior));

                case ReplicatonNodeState.Offline:
                    return(ReplicationTopologyDestinationNode.Offline(destination.ConnectionStringOptions.Url, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior));

                default:
                    throw new NotSupportedException(state.ToString());
                }
            }

            string error;
            ReplicationTopologyRootNode rootNode;

            if (TryGetSchema(destination.ConnectionStringOptions.Url, destination.ConnectionStringOptions, out rootNode, out error))
            {
                var node = ReplicationTopologyDestinationNode.Online(destination.ConnectionStringOptions.Url, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior);
                node.Destinations = rootNode.Destinations;
                node.Sources      = rootNode.Sources;
                node.Errors       = rootNode.Errors;

                return(node);
            }

            var offline = ReplicationTopologyDestinationNode.Offline(destination.ConnectionStringOptions.Url, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior);

            if (string.IsNullOrEmpty(error) == false)
            {
                offline.Errors.Add(error);
            }

            return(offline);
        }
        public void ExtractDocumentIds(ServerInfo serverInfo, Action <string> successAction, Action skippedAction)
        {
            var replicationDocument = GetReplicationDocument();

            var replicationDestination = replicationDocument
                                         .Destinations
                                         .FirstOrDefault(x => FetchTargetServerUrl(x).Equals(serverInfo.DestinationUrl, StringComparison.CurrentCultureIgnoreCase) &&
                                                         x.Database.Equals(serverInfo.DatabaseName, StringComparison.CurrentCultureIgnoreCase));

            if (replicationDestination == null)
            {
                throw new InvalidOperationException($"Couldn't find replication destination for url: {serverInfo.DestinationUrl} and database: {serverInfo.DatabaseName}");
            }

            var replicationStrategy = ReplicationTask.GetConnectionOptions(replicationDestination, database);
            var sourcesDocument     = replicationTask.GetLastReplicatedEtagFrom(replicationStrategy);

            if (sourcesDocument == null)
            {
                throw new InvalidOperationException($"Couldn't get last replicated etag for " +
                                                    $"destination url: {serverInfo.DestinationUrl} and database: {serverInfo.DatabaseName}");
            }

            database.TransactionalStorage.Batch(actions =>
            {
                var earlyExit = new Reference <bool>();

                //get document count since last replicated etag
                var documentIds = actions.Documents.GetDocumentIdsAfterEtag(
                    sourcesDocument.LastDocumentEtag, int.MaxValue,
                    WillDocumentBeReplicated(replicationStrategy, sourcesDocument.ServerInstanceId.ToString(), skippedAction),
                    earlyExit, database.WorkContext.CancellationToken);

                foreach (var documentId in documentIds)
                {
                    successAction(documentId);
                }
            });
        }
Example #6
0
        private ReplicationTopologyDestinationNode HandleDestination(ReplicationDestination replicationDestination)
        {
            var destination = ReplicationTask.GetConnectionOptions(replicationDestination, database);

            string error;
            string targetServerUrl;

            // since each server can be addresses using both dns and ips we normalize connection string url by fetching target server url
            // it should give us consistent urls
            if (FetchTargetServerUrl(destination.ConnectionStringOptions.Url, destination.ConnectionStringOptions, out targetServerUrl, out error) == false)
            {
                var offlineNode = ReplicationTopologyDestinationNode.Offline(destination.ConnectionStringOptions.Url, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior);

                if (string.IsNullOrEmpty(error) == false)
                {
                    offlineNode.Errors.Add(error);
                }

                return(offlineNode);
            }

            if (replicationDestination.Disabled)
            {
                return(ReplicationTopologyDestinationNode.Disabled(targetServerUrl, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior));
            }

            if (from.Contains(targetServerUrl))
            {
                var state = CheckDestinationConnectionState(destination);
                switch (state)
                {
                case ReplicatonNodeState.Online:
                    return(ReplicationTopologyDestinationNode.Online(targetServerUrl, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior));

                case ReplicatonNodeState.Offline:
                    return(ReplicationTopologyDestinationNode.Offline(targetServerUrl, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior));

                default:
                    throw new NotSupportedException(state.ToString());
                }
            }


            ReplicationTopologyRootNode rootNode;

            if (TryGetSchema(destination.ConnectionStringOptions.Url, destination.ConnectionStringOptions, out rootNode, out error))
            {
                var node = ReplicationTopologyDestinationNode.Online(targetServerUrl, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior);
                node.Destinations = rootNode.Destinations;
                node.Sources      = rootNode.Sources;
                node.Errors       = rootNode.Errors;

                return(node);
            }

            var offline = ReplicationTopologyDestinationNode.Offline(targetServerUrl, database.TransactionalStorage.Id, destination.ReplicationOptionsBehavior);

            if (string.IsNullOrEmpty(error) == false)
            {
                offline.Errors.Add(error);
            }

            return(offline);
        }