Example #1
0
        public void CanReplicateIndex()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(8077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer))
                    using (var destinationServer = GetNewServer(8078))
                        using (var destination = NewRemoteDocumentStore(ravenDbServer: destinationServer))
                        {
                            CreateDatabaseWithReplication(source, "testDB");
                            CreateDatabaseWithReplication(destination, "testDB");

                            //turn-off automatic index replication - precaution
                            source.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;
                            SetupReplication(source, "testDB", destination);

                            //make sure not to replicate the index automatically
                            var userIndex = new UserIndex();
                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(userIndex.IndexName, userIndex.CreateIndexDefinition());

                            var indexStatsBeforeReplication = destination.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes;
                            Assert.False(indexStatsBeforeReplication.Any(index => index.Name.Equals(userIndex.IndexName, StringComparison.InvariantCultureIgnoreCase)));

                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-indexes?indexName={1}", source.Url, userIndex.IndexName);
                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, "POST", new RavenConnectionStringOptions
                            {
                                Url = source.Url
                            });
                            replicationRequest.ExecuteRequest();

                            var indexStatsAfterReplication = destination.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes;
                            Assert.True(indexStatsAfterReplication.Any(index => index.Name.Equals(userIndex.IndexName, StringComparison.InvariantCultureIgnoreCase)));
                        }
        }
Example #2
0
        private void ReplicateSingleSideBySideIndex(ReplicationStrategy destination, IndexDefinition indexDefinition, IndexDefinition sideBySideIndexDefinition)
        {
            var url = $"{destination.ConnectionStringOptions.Url}/replication/side-by-side?{GetDebugInformation()}";
            IndexReplaceDocument indexReplaceDocument;

            try
            {
                indexReplaceDocument = Database.Documents.Get(Constants.IndexReplacePrefix + sideBySideIndexDefinition.Name, null).DataAsJson.JsonDeserialization <IndexReplaceDocument>();
            }
            catch (Exception e)
            {
                Log.Warn("Cannot get side-by-side index replacement document. Aborting operation. (this exception should not happen and the cause should be investigated)", e);
                return;
            }

            var sideBySideReplicationInfo = new SideBySideReplicationInfo
            {
                Index                = indexDefinition,
                SideBySideIndex      = sideBySideIndexDefinition,
                OriginDatabaseId     = destination.CurrentDatabaseId,
                IndexReplaceDocument = indexReplaceDocument
            };

            var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethod.Post, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination));

            replicationRequest.Write(RavenJObject.FromObject(sideBySideReplicationInfo));
            replicationRequest.ExecuteRequest();
        }
        private void ReplicateTransformerDeletionIfNeeded(List <JsonDocument> transformerTombstones, ReplicationStrategy destination, Dictionary <string, int> replicatedTransformerTombstones)
        {
            if (transformerTombstones.Count == 0)
            {
                return;
            }

            foreach (var tombstone in transformerTombstones)
            {
                try
                {
                    int value;
                    if (Database.Transformers.GetTransformerDefinition(tombstone.Key) != null) //if in the meantime the transformer was recreated under the same name
                    {
                        replicatedTransformerTombstones.TryGetValue(tombstone.Key, out value);
                        replicatedTransformerTombstones[tombstone.Key] = value + 1;
                        continue;
                    }

                    var url = string.Format("{0}/transformers/{1}?{2}", destination.ConnectionStringOptions.Url, Uri.EscapeUriString(tombstone.Key), GetDebugInformation());
                    var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethods.Delete, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination));
                    replicationRequest.Write(RavenJObject.FromObject(EmptyRequestBody));
                    replicationRequest.ExecuteRequest();
                    Log.Info("Replicated transformer deletion (transformer name = {0})", tombstone.Key);
                    replicatedTransformerTombstones.TryGetValue(tombstone.Key, out value);
                    replicatedTransformerTombstones[tombstone.Key] = value + 1;
                }
                catch (Exception e)
                {
                    Replication.HandleRequestBufferingErrors(e, destination);

                    Log.ErrorException(string.Format("Failed to replicate transformer deletion (transformer name = {0})", tombstone.Key), e);
                }
            }
        }
Example #4
0
 public IndexReplicationTask(DocumentDatabase database, HttpRavenRequestFactory httpRavenRequestFactory, ReplicationTask replication)
     : base(database, httpRavenRequestFactory, replication)
 {
     replicationFrequency = TimeSpan.FromSeconds(database.Configuration.IndexAndTransformerReplicationLatencyInSec); //by default 10 min
     lastQueriedFrequency = TimeSpan.FromSeconds(database.Configuration.TimeToWaitBeforeRunningIdleIndexes.TotalSeconds / 2);
     TimeToWaitBeforeSendingDeletesOfIndexesToSiblings = TimeSpan.FromMinutes(1);
 }
 public SynchronizationTopologyDiscoverer(RavenFileSystem filesystem, RavenJArray @from, int ttl, ILog log)
 {
     this.filesystem = filesystem;
     this.ttl        = ttl;
     this.log        = log;
     this.@from      = @from;
     requestFactory  = new HttpRavenRequestFactory();
 }
Example #6
0
 public CountersReplicationTopologyDiscoverer(CounterStorage counterStorage, RavenJArray @from, int ttl, ILog log)
 {
     this.counterStorage = counterStorage;
     this.ttl            = ttl;
     this.log            = log;
     this.@from          = @from;
     requestFactory      = new HttpRavenRequestFactory();
 }
        public TransformerReplicationTask(DocumentDatabase database, HttpRavenRequestFactory httpRavenRequestFactory, ReplicationTask replication)
            : base(database, httpRavenRequestFactory)
        {
            this.replication = replication;

            replicationFrequency = database.Configuration.Replication.IndexAndTransformerReplicationLatency.AsTimeSpan; //by default 10 min
            TimeToWaitBeforeSendingDeletesOfTransformersToSiblings = TimeSpan.FromMinutes(1);
        }
Example #8
0
 public ReplicationTopologyDiscoverer(DocumentDatabase database, RavenJArray @from, int ttl, ILog log)
 {
     this.database  = database;
     this.ttl       = ttl;
     this.log       = log;
     this.@from     = @from;
     requestFactory = new HttpRavenRequestFactory();
 }
        public void should_replicate_only_updated_transformer()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(8077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer, fiddler: true))
                    using (var destinationServer = GetNewServer(8078))
                        using (var destination = NewRemoteDocumentStore(ravenDbServer: destinationServer, fiddler: true))
                        {
                            CreateDatabaseWithReplication(source, "testDB");
                            CreateDatabaseWithReplication(destination, "testDB");

                            source.Conventions.IndexAndTransformerReplicationMode      = IndexAndTransformerReplicationMode.None;
                            destination.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;

                            SetupReplication(source, "testDB", store => false, destination);
                            SetupReplication(destination, "testDB", store => false, source);

                            for (var i = 0; i < 30; i++)
                            {
                                //just for starting the initial index and transformer replication
                                source.DatabaseCommands.ForDatabase("testDB").Put("test" + i, Etag.Empty, new RavenJObject(), new RavenJObject());
                                destination.DatabaseCommands.ForDatabase("testDB").Put("test" + (i + 50), Etag.Empty, new RavenJObject(), new RavenJObject());
                            }

                            WaitForDocument(destination.DatabaseCommands.ForDatabase("testDB"), "test29");
                            WaitForDocument(source.DatabaseCommands.ForDatabase("testDB"), "test79");

                            var userTransformer = new UserWithoutExtraInfoTransformer();
                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(userTransformer.TransformerName, userTransformer.CreateTransformerDefinition());

                            //replicating transformer from the source
                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-transformers?op=replicate-all", source.Url);
                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, HttpMethods.Post, new RavenConnectionStringOptions
                            {
                                Url = source.Url
                            });
                            replicationRequest.ExecuteRequest();

                            var updatedUserTransformer = new UserWithoutExtraInfoTransformer_Extended();
                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(userTransformer.TransformerName, updatedUserTransformer.CreateTransformerDefinition());

                            var transformer = source.DatabaseCommands.ForDatabase("testDB").GetTransformer(userTransformer.TransformerName);
                            Assert.True(updatedUserTransformer.CreateTransformerDefinition().TransformResults.Equals(transformer.TransformResults));

                            //replicating transformer from the destination
                            replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-transformers?op=replicate-all", destination.Url);
                            replicationRequest    = requestFactory.Create(replicationRequestUrl, HttpMethods.Post, new RavenConnectionStringOptions
                            {
                                Url = destination.Url
                            });
                            replicationRequest.ExecuteRequest();

                            //the new transformer shouldn't be overwritten
                            transformer = source.DatabaseCommands.ForDatabase("testDB").GetTransformer(userTransformer.TransformerName);
                            Assert.True(updatedUserTransformer.CreateTransformerDefinition().TransformResults.Equals(transformer.TransformResults));
                        }
        }
Example #10
0
        public void StartReplication()
        {
            var replicationTask = new Task(ReplicationAction, TaskCreationOptions.LongRunning);

            httpRavenRequestFactory = new HttpRavenRequestFactory {
                RequestTimeoutInMs = storage.ReplicationTimeoutInMs
            };
            replicationTask.Start();
        }
Example #11
0
        public void Should_replicate_all_transformers_only_to_specific_destination_if_relevant_endpoint_is_hit()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(8077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer, fiddler: true))
                    using (var destinationServer1 = GetNewServer(8078))
                        using (var destination1 = NewRemoteDocumentStore(ravenDbServer: destinationServer1, fiddler: true))
                            using (var destinationServer2 = GetNewServer())
                                using (var destination2 = NewRemoteDocumentStore(ravenDbServer: destinationServer2, fiddler: true))
                                    using (var destinationServer3 = GetNewServer(8081))
                                        using (var destination3 = NewRemoteDocumentStore(ravenDbServer: destinationServer3, fiddler: true))
                                        {
                                            CreateDatabaseWithReplication(source, "testDB");
                                            CreateDatabaseWithReplication(destination1, "testDB");
                                            CreateDatabaseWithReplication(destination2, "testDB");
                                            CreateDatabaseWithReplication(destination3, "testDB");

                                            //make sure replication is off for indexes/transformers
                                            source.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;

                                            var userTransformer       = new UserWithoutExtraInfoTransformer();
                                            var anotherTransformer    = new AnotherTransformer();
                                            var yetAnotherTransformer = new YetAnotherTransformer();

                                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(userTransformer.TransformerName, userTransformer.CreateTransformerDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(anotherTransformer.TransformerName, anotherTransformer.CreateTransformerDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(yetAnotherTransformer.TransformerName, yetAnotherTransformer.CreateTransformerDefinition());

                                            var expectedTransformerNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase)
                                            {
                                                userTransformer.TransformerName,
                                                anotherTransformer.TransformerName,
                                                yetAnotherTransformer.TransformerName
                                            };

                                            // ReSharper disable once AccessToDisposedClosure
                                            var destinations = SetupReplication(source, "testDB", store => false, destination1, destination2, destination3);

                                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-transformers?op=replicate-all-to-destination", source.Url);
                                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, "POST", new RavenConnectionStringOptions
                                            {
                                                Url = source.Url
                                            });
                                            replicationRequest.Write(RavenJObject.FromObject(destinations[1]));
                                            replicationRequest.ExecuteRequest();

                                            var transformerNamesAtDestination1 = destination1.DatabaseCommands.ForDatabase("testDB").GetTransformers(0, 1024);
                                            var transformerNamesAtDestination2 = destination2.DatabaseCommands.ForDatabase("testDB").GetTransformers(0, 1024);
                                            var transformerNamesAtDestination3 = destination3.DatabaseCommands.ForDatabase("testDB").GetTransformers(0, 1024);

                                            Assert.Equal(0, transformerNamesAtDestination1.Length);
                                            Assert.True(expectedTransformerNames.SetEquals(transformerNamesAtDestination2.Select(x => x.Name).ToArray()));
                                            Assert.Equal(0, transformerNamesAtDestination3.Length);
                                        }
        }
Example #12
0
        public void Replicate_all_transformers_should_respect_disable_replication_flag()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(8077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer, fiddler: true))
                    using (var destinationServer1 = GetNewServer(8078))
                        using (var destination1 = NewRemoteDocumentStore(ravenDbServer: destinationServer1, fiddler: true))
                            using (var destinationServer2 = GetNewServer())
                                using (var destination2 = NewRemoteDocumentStore(ravenDbServer: destinationServer2, fiddler: true))
                                    using (var destinationServer3 = GetNewServer(8081))
                                        using (var destination3 = NewRemoteDocumentStore(ravenDbServer: destinationServer3, fiddler: true))
                                        {
                                            CreateDatabaseWithReplication(source, "testDB");
                                            CreateDatabaseWithReplication(destination1, "testDB");
                                            CreateDatabaseWithReplication(destination2, "testDB");
                                            CreateDatabaseWithReplication(destination3, "testDB");

                                            //make sure replication is off for indexes/transformers
                                            source.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;

                                            var userTransformer              = new UserWithoutExtraInfoTransformer();
                                            var anotherTransformer           = new AnotherTransformer();
                                            var yetAnotherTransformer        = new YetAnotherTransformer();
                                            var conflictDocumentsTransformer = new RavenConflictDocumentsTransformer(); // #RavenDB-3981

                                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(userTransformer.TransformerName, userTransformer.CreateTransformerDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(anotherTransformer.TransformerName, anotherTransformer.CreateTransformerDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutTransformer(yetAnotherTransformer.TransformerName, yetAnotherTransformer.CreateTransformerDefinition());

                                            var expectedTransformerNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase)
                                            {
                                                userTransformer.TransformerName,
                                                anotherTransformer.TransformerName,
                                                yetAnotherTransformer.TransformerName,
                                            };

                                            // ReSharper disable once AccessToDisposedClosure
                                            SetupReplication(source, "testDB", store => store == destination2, destination1, destination2, destination3);

                                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-transformers?op=replicate-all", source.Url);
                                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, HttpMethods.Post, new RavenConnectionStringOptions
                                            {
                                                Url = source.Url
                                            });
                                            replicationRequest.ExecuteRequest();

                                            var transformerNamesAtDestination1 = destination1.DatabaseCommands.ForDatabase("testDB").GetTransformers(0, 1024).Where(x => x.Name != conflictDocumentsTransformer.TransformerName);
                                            var transformerNamesAtDestination2 = destination2.DatabaseCommands.ForDatabase("testDB").GetTransformers(0, 1024).Where(x => x.Name != conflictDocumentsTransformer.TransformerName);
                                            var transformerNamesAtDestination3 = destination3.DatabaseCommands.ForDatabase("testDB").GetTransformers(0, 1024).Where(x => x.Name != conflictDocumentsTransformer.TransformerName);

                                            Assert.True(expectedTransformerNames.SetEquals(transformerNamesAtDestination1.Select(x => x.Name).ToArray()));
                                            Assert.Equal(0, transformerNamesAtDestination2.Count());
                                            Assert.True(expectedTransformerNames.SetEquals(transformerNamesAtDestination3.Select(x => x.Name).ToArray()));
                                        }
        }
Example #13
0
        private void ReplicateIndexesMultiPut(ReplicationStrategy destination, List <IndexToAdd> indexesToAdd)
        {
            var serializedIndexDefinitions = RavenJToken.FromObject(indexesToAdd.ToArray());
            var url = $"{destination.ConnectionStringOptions.Url}/indexes?{GetDebugInformation()}";

            var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethods.Put, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination));

            replicationRequest.Write(serializedIndexDefinitions);
            replicationRequest.ExecuteRequest();
        }
Example #14
0
        public void Replicate_all_indexes_should_respect_disable_indexing_flag()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(9077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer, fiddler: true))
                    using (var destinationServer1 = GetNewServer(9078))
                        using (var destination1 = NewRemoteDocumentStore(ravenDbServer: destinationServer1, fiddler: true))
                            using (var destinationServer2 = GetNewServer())
                                using (var destination2 = NewRemoteDocumentStore(ravenDbServer: destinationServer2, fiddler: true))
                                    using (var destinationServer3 = GetNewServer(9081))
                                        using (var destination3 = NewRemoteDocumentStore(ravenDbServer: destinationServer3, fiddler: true))
                                        {
                                            CreateDatabaseWithReplication(source, "testDB");
                                            CreateDatabaseWithReplication(destination1, "testDB");
                                            CreateDatabaseWithReplication(destination2, "testDB");
                                            CreateDatabaseWithReplication(destination3, "testDB");

                                            //turn-off automatic index replication - precaution
                                            source.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;
                                            // ReSharper disable once AccessToDisposedClosure
                                            //we setup replication so replication to destination2 will have "disabled" flag
                                            SetupReplication(source, "testDB", store => store == destination2, destination1, destination2, destination3);

                                            //make sure not to replicate the index automatically
                                            var userIndex           = new UserIndex();
                                            var anotherUserIndex    = new AnotherUserIndex();
                                            var yetAnotherUserIndex = new YetAnotherUserIndex();
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(userIndex.IndexName, userIndex.CreateIndexDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(anotherUserIndex.IndexName, anotherUserIndex.CreateIndexDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(yetAnotherUserIndex.IndexName, yetAnotherUserIndex.CreateIndexDefinition());

                                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-indexes?op=replicate-all", source.Url);
                                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, "POST", new RavenConnectionStringOptions
                                            {
                                                Url = source.Url
                                            });
                                            replicationRequest.ExecuteRequest();

                                            var expectedIndexNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase)
                                            {
                                                userIndex.IndexName, anotherUserIndex.IndexName, yetAnotherUserIndex.IndexName
                                            };
                                            var indexStatsAfterReplication1 = destination1.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes.Select(x => x.Name);
                                            Assert.True(expectedIndexNames.SetEquals(indexStatsAfterReplication1));


                                            var indexStatsAfterReplication3 = destination3.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes.Select(x => x.Name);
                                            Assert.True(expectedIndexNames.SetEquals(indexStatsAfterReplication3));

                                            //since destination2 has disabled flag - indexes should not replicate to here
                                            var indexStatsAfterReplication2 = destination2.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes.Select(x => x.Name);
                                            Assert.Empty(indexStatsAfterReplication2);
                                        }
        }
Example #15
0
        public void Should_replicate_all_indexes_only_to_specific_destination_if_relevant_endpoint_hit()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(8077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer))
                    using (var destinationServer1 = GetNewServer(8078))
                        using (var destination1 = NewRemoteDocumentStore(ravenDbServer: destinationServer1))
                            using (var destinationServer2 = GetNewServer())
                                using (var destination2 = NewRemoteDocumentStore(ravenDbServer: destinationServer2))
                                    using (var destinationServer3 = GetNewServer(8081))
                                        using (var destination3 = NewRemoteDocumentStore(ravenDbServer: destinationServer3))
                                        {
                                            CreateDatabaseWithReplication(source, "testDB");
                                            CreateDatabaseWithReplication(destination1, "testDB");
                                            CreateDatabaseWithReplication(destination2, "testDB");
                                            CreateDatabaseWithReplication(destination3, "testDB");

                                            //turn-off automatic index replication - precaution
                                            source.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;
                                            // ReSharper disable once AccessToDisposedClosure
                                            var destinationDocuments = SetupReplication(source, "testDB", store => false, destination1, destination2, destination3);

                                            //make sure not to replicate the index automatically
                                            var userIndex           = new UserIndex();
                                            var anotherUserIndex    = new AnotherUserIndex();
                                            var yetAnotherUserIndex = new YetAnotherUserIndex();
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(userIndex.IndexName, userIndex.CreateIndexDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(anotherUserIndex.IndexName, anotherUserIndex.CreateIndexDefinition());
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(yetAnotherUserIndex.IndexName, yetAnotherUserIndex.CreateIndexDefinition());

                                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-indexes?op=replicate-all-to-destination", source.Url);
                                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, "POST", new RavenConnectionStringOptions
                                            {
                                                Url = source.Url
                                            });

                                            replicationRequest.Write(RavenJObject.FromObject(destinationDocuments[1]));
                                            replicationRequest.ExecuteRequest();

                                            var expectedIndexNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase)
                                            {
                                                userIndex.IndexName, anotherUserIndex.IndexName, yetAnotherUserIndex.IndexName
                                            };
                                            var indexStatsAfterReplication1 = destination1.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes.Select(x => x.Name);
                                            var indexStatsAfterReplication2 = destination2.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes.Select(x => x.Name);
                                            var indexStatsAfterReplication3 = destination3.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes.Select(x => x.Name);

                                            Assert.Equal(0, indexStatsAfterReplication1.Count());
                                            Assert.True(expectedIndexNames.SetEquals(indexStatsAfterReplication2));
                                            Assert.Equal(0, indexStatsAfterReplication3.Count());
                                        }
        }
        public DocumentsLeftToReplicate(DocumentDatabase database)
        {
            this.database  = database;
            DatabaseId     = database.TransactionalStorage.Id.ToString();
            requestFactory = new HttpRavenRequestFactory();

            replicationTask = database.StartupTasks.OfType <ReplicationTask>().FirstOrDefault();
            if (replicationTask == null)
            {
                throw new InvalidOperationException("Couldn't locate ReplicationTask");
            }
        }
Example #17
0
        public void SendLastQueried()
        {
            if (Database.Disposed)
            {
                return;
            }

            try
            {
                using (CultureHelper.EnsureInvariantCulture())
                {
                    var relevantIndexLastQueries = new Dictionary <string, DateTime>();
                    var relevantIndexes          = Database.Statistics.Indexes.Where(indexStats => indexStats.IsInvalidIndex == false && indexStats.Priority != IndexingPriority.Error && indexStats.Priority != IndexingPriority.Disabled && indexStats.LastQueryTimestamp.HasValue);

                    foreach (var relevantIndex in relevantIndexes)
                    {
                        relevantIndexLastQueries[relevantIndex.Name] = relevantIndex.LastQueryTimestamp.GetValueOrDefault();
                    }

                    if (relevantIndexLastQueries.Count == 0)
                    {
                        return;
                    }

                    var destinations = GetReplicationDestinations(x => x.SkipIndexReplication == false);

                    foreach (var destination in destinations)
                    {
                        try
                        {
                            string url = destination.ConnectionStringOptions.Url + "/indexes/last-queried";

                            var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethods.Post, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination));
                            replicationRequest.Write(RavenJObject.FromObject(relevantIndexLastQueries));
                            replicationRequest.ExecuteRequest();
                        }
                        catch (Exception e)
                        {
                            Replication.HandleRequestBufferingErrors(e, destination);

                            Log.WarnException("Could not update last query time of " + destination.ConnectionStringOptions.Url, e);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.ErrorException("Failed to send last queried timestamp of indexes", e);
            }
        }
Example #18
0
        public void PutAndDeleteShouldBePropagated(int numberOfNodes)
        {
            var clusterStores = CreateRaftCluster(numberOfNodes, activeBundles: "Replication", configureStore: store => store.Conventions.FailoverBehavior = FailoverBehavior.ReadFromLeaderWriteToLeader);

            SetupClusterConfiguration(clusterStores);


            var store1 = clusterStores[0];

            servers.ForEach(server =>
            {
                var sourceDatabase        = AsyncHelpers.RunSync(() => server.Server.GetDatabaseInternal(store1.DefaultDatabase));
                var sourceReplicationTask = sourceDatabase.StartupTasks.OfType <ReplicationTask>().First();
                sourceReplicationTask.IndexReplication.TimeToWaitBeforeSendingDeletesOfIndexesToSiblings = TimeSpan.FromSeconds(0);
            });


            store1.DatabaseCommands.PutIndex("Test/Index", new Test_Index().CreateIndexDefinition(), true);

            var requestFactory        = new HttpRavenRequestFactory();
            var replicationRequestUrl = string.Format("{0}/replication/replicate-indexes?op=replicate-all", store1.Url.ForDatabase(store1.DefaultDatabase));

            if (numberOfNodes > 1)
            {
                var replicationRequest = requestFactory.Create(replicationRequestUrl, HttpMethod.Post, new RavenConnectionStringOptions {
                    Url = store1.Url
                });
                replicationRequest.ExecuteRequest();
            }

            using (ForceNonClusterRequests(clusterStores))
            {
                clusterStores.ForEach(store => WaitFor(store.DatabaseCommands, commands => commands.GetIndex("Test/Index") != null, TimeSpan.FromMinutes(1)));
            }

            store1.DatabaseCommands.DeleteIndex("Test/Index");
            if (numberOfNodes > 1)
            {
                var replicationRequest = requestFactory.Create(replicationRequestUrl, HttpMethod.Post, new RavenConnectionStringOptions {
                    Url = store1.Url
                });
                replicationRequest.ExecuteRequest();
            }

            using (ForceNonClusterRequests(clusterStores))
            {
                clusterStores.ForEach(store => WaitFor(store.DatabaseCommands, commands => commands.GetIndex("Test/Index") == null, TimeSpan.FromMinutes(1)));
            }
        }
Example #19
0
        public ReplicationTopologyDiscoverer(DocumentDatabase database, IEnumerable <string> @from, int ttl, ILog log)
        {
            this.database   = database;
            this.ttl        = ttl;
            this.log        = log;
            this.@from      = new HashSet <string>(@from, StringComparer.OrdinalIgnoreCase);
            requestFactory  = new HttpRavenRequestFactory();
            currentServerId = database.TransactionalStorage.Id;

            replicationTask = database.StartupTasks.OfType <ReplicationTask>().FirstOrDefault();
            if (replicationTask == null)
            {
                throw new InvalidOperationException("Couldn't locate ReplicationTask");
            }
        }
Example #20
0
        public ReplicationTopologyDiscoverer(DocumentDatabase database, RavenJArray @from, int ttl, ILog log)
        {
            this.database   = database;
            this.ttl        = ttl;
            this.log        = log;
            this.@from      = @from;
            requestFactory  = new HttpRavenRequestFactory();
            currentServerId = database.TransactionalStorage.Id;

            replicationTask = database.StartupTasks.OfType <ReplicationTask>().FirstOrDefault();
            if (replicationTask == null)
            {
                throw new InvalidOperationException("Couldn't locate ReplicationTask");
            }
        }
        private ReplicationInfoStatus[] CheckDestinations(ReplicationDocument replicationDocument)
        {
            var results = new ReplicationInfoStatus[replicationDocument.Destinations.Count];

            Parallel.ForEach(replicationDocument.Destinations, (replicationDestination, state, i) =>
            {
                var url = replicationDestination.Url;

                if (!url.ToLower().Contains("/databases/"))
                {
                    url += "/databases/" + replicationDestination.Database;
                }

                var result = new ReplicationInfoStatus
                {
                    Url    = url,
                    Status = "Valid",
                    Code   = (int)HttpStatusCode.OK
                };

                results[i] = result;

                var ravenConnectionStringOptions = new RavenConnectionStringOptions
                {
                    ApiKey          = replicationDestination.ApiKey,
                    DefaultDatabase = replicationDestination.Database,
                };
                if (string.IsNullOrEmpty(replicationDestination.Username) == false)
                {
                    ravenConnectionStringOptions.Credentials = new NetworkCredential(replicationDestination.Username,
                                                                                     replicationDestination.Password,
                                                                                     replicationDestination.Domain ?? string.Empty);
                }

                var requestFactory = new HttpRavenRequestFactory();
                var request        = requestFactory.Create(url + "/replication/info", HttpMethods.Post, ravenConnectionStringOptions);
                try
                {
                    request.ExecuteRequest();
                }
                catch (WebException e)
                {
                    FillStatus(result, e);
                }
            });

            return(results);
        }
Example #22
0
 public void CompactUpdateMessagesShouldNotAppearInMessages(string requestedStorage)
 {
     using (var documentStore = NewRemoteDocumentStore(requestedStorage: requestedStorage, databaseName: "Test", runInMemory: false))
     {
         using (var session = documentStore.OpenSession())
         {
             session.Store(new RavenJObject());
             session.SaveChanges();
         }
         var ravenHtttpFactory = new HttpRavenRequestFactory();
         var request           = ravenHtttpFactory.Create("http://localhost:8079/admin/compact?database=Test", "POST", new RavenConnectionStringOptions());
         var response          = request.ExecuteRequest <RavenJObject>();
         using (var systemDocumentStore = new DocumentStore()
         {
             Url = "http://localhost:8079"
         }.Initialize())
         {
             using (var session = systemDocumentStore.OpenSession())
             {
                 var stopeWatch = new Stopwatch();
                 stopeWatch.Start();
                 do
                 {
                     if (stopeWatch.Elapsed >= timeout)
                     {
                         throw new TimeoutException("Waited to long for test to complete compaction.");
                     }
                     var statusRequest = ravenHtttpFactory.Create("http://localhost:8079/operation/status?id=" + response.Value <string>("OperationId"), "GET", new RavenConnectionStringOptions());
                     var status        = statusRequest.ExecuteRequest <RavenJObject>();
                     if (status.Value <bool>("Completed"))
                     {
                         var compactStatus = session.Load <CompactStatus>(CompactStatus.RavenDatabaseCompactStatusDocumentKey("Test"));
                         Assert.Equal(compactStatus.Messages.Count, storageToExpectedLength[requestedStorage]);
                         return;
                     }
                     else if (status.Value <bool>("Faulted"))
                     {
                         throw new Exception("Something went wrong, compaction was not successful");
                     }
                     Thread.Sleep(1000);
                 } while (true);
             }
         }
     }
 }
Example #23
0
        private void ReplicateIndexDeletionIfNeeded(
            List <JsonDocument> indexTombstones,
            ReplicationStrategy destination,
            Dictionary <string, int> replicatedIndexTombstones)
        {
            if (indexTombstones.Count == 0)
            {
                return;
            }

            foreach (var tombstone in indexTombstones)
            {
                try
                {
                    int value;
                    //In case the index was recreated under the same name we will increase the destination count for this tombstone
                    //As if we sent the delete request but without actually sending the request, ending with a NOOP and deleting the index tombstone.
                    if (Database.IndexStorage.HasIndex(tombstone.Key))
                    {
                        replicatedIndexTombstones.TryGetValue(tombstone.Key, out value);
                        replicatedIndexTombstones[tombstone.Key] = value + 1;
                        continue;
                    }

                    var url = string.Format("{0}/indexes/{1}?{2}&{3}",
                                            destination.ConnectionStringOptions.Url,
                                            Uri.EscapeUriString(tombstone.Key),
                                            GetTombstoneVersion(tombstone, IndexDefinitionStorage.IndexVersionKey, Constants.IndexVersion),
                                            GetDebugInformation());
                    var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethods.Delete, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination));
                    replicationRequest.Write(RavenJObject.FromObject(EmptyRequestBody));
                    replicationRequest.ExecuteRequest();
                    Log.Info("Replicated index deletion (index name = {0})", tombstone.Key);

                    replicatedIndexTombstones.TryGetValue(tombstone.Key, out value);
                    replicatedIndexTombstones[tombstone.Key] = value + 1;
                }
                catch (Exception e)
                {
                    Replication.HandleRequestBufferingErrors(e, destination);

                    Log.ErrorException(string.Format("Failed to replicate index deletion (index name = {0})", tombstone.Key), e);
                }
            }
        }
Example #24
0
        public void Should_skip_index_replication_if_serverside_flag_is_true()
        {
            var requestFactory = new HttpRavenRequestFactory();

            using (var sourceServer = GetNewServer(8077))
                using (var source = NewRemoteDocumentStore(ravenDbServer: sourceServer))
                    using (var destinationServer1 = GetNewServer(8078))
                        using (var destination1 = NewRemoteDocumentStore(ravenDbServer: destinationServer1))
                            using (var destinationServer2 = GetNewServer())
                                using (var destination2 = NewRemoteDocumentStore(ravenDbServer: destinationServer2))
                                    using (var destinationServer3 = GetNewServer(8081))
                                        using (var destination3 = NewRemoteDocumentStore(ravenDbServer: destinationServer3))
                                        {
                                            CreateDatabaseWithReplication(source, "testDB");
                                            CreateDatabaseWithReplication(destination1, "testDB");
                                            CreateDatabaseWithReplication(destination2, "testDB");
                                            CreateDatabaseWithReplication(destination3, "testDB");

                                            //turn-off automatic index replication - precaution
                                            source.Conventions.IndexAndTransformerReplicationMode = IndexAndTransformerReplicationMode.None;
                                            // ReSharper disable once AccessToDisposedClosure
                                            SetupReplication(source, "testDB", store => store == destination2, destination1, destination2, destination3);

                                            //make sure not to replicate the index automatically
                                            var userIndex = new UserIndex();
                                            source.DatabaseCommands.ForDatabase("testDB").PutIndex(userIndex.IndexName, userIndex.CreateIndexDefinition());

                                            var replicationRequestUrl = string.Format("{0}/databases/testDB/replication/replicate-indexes?op=replication&indexName={1}", source.Url, userIndex.IndexName);
                                            var replicationRequest    = requestFactory.Create(replicationRequestUrl, "POST", new RavenConnectionStringOptions
                                            {
                                                Url = source.Url
                                            });
                                            replicationRequest.ExecuteRequest();

                                            var indexStatsAfterReplication = destination1.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes;
                                            Assert.True(indexStatsAfterReplication.Any(index => index.Name.Equals(userIndex.IndexName, StringComparison.InvariantCultureIgnoreCase)));

                                            //this one should not have replicated index -> because of SkipIndexReplication = true in ReplicationDocument of source
                                            indexStatsAfterReplication = destination2.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes;
                                            Assert.False(indexStatsAfterReplication.Any(index => index.Name.Equals(userIndex.IndexName, StringComparison.InvariantCultureIgnoreCase)));

                                            indexStatsAfterReplication = destination3.DatabaseCommands.ForDatabase("testDB").GetStatistics().Indexes;
                                            Assert.True(indexStatsAfterReplication.Any(index => index.Name.Equals(userIndex.IndexName, StringComparison.InvariantCultureIgnoreCase)));
                                        }
        }
        private void ReplicateSingleTransformer(ReplicationStrategy destination, TransformerDefinition definition)
        {
            try
            {
                var clonedTransformer = definition.Clone();
                clonedTransformer.TransfomerId = 0;

                var url = destination.ConnectionStringOptions.Url + "/transformers/" + Uri.EscapeUriString(definition.Name) + "?" + GetDebugInformation();
                var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethod.Put, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination));
                replicationRequest.Write(RavenJObject.FromObject(clonedTransformer));
                replicationRequest.ExecuteRequest();
            }
            catch (Exception e)
            {
                Replication.HandleRequestBufferingErrors(e, destination);

                Log.WarnException("Could not replicate transformer " + definition.Name + " to " + destination.ConnectionStringOptions.Url, e);
            }
        }
Example #26
0
        public void Execute(DocumentDatabase database)
        {
            docDb = database;
            var replicationRequestTimeoutInMs =
                docDb.Configuration.GetConfigurationValue <int>("Raven/Replication/ReplicationRequestTimeout") ?? 7500;

            httpRavenRequestFactory = new HttpRavenRequestFactory {
                RequestTimeoutInMs = replicationRequestTimeoutInMs
            };

            var thread = new Thread(Execute)
            {
                IsBackground = true,
                Name         = "Replication Thread"
            };

            // make sure that the doc db waits for the replication thread shutdown
            docDb.ExtensionsState.TryAdd(thread, new DisposableAction(thread.Join));
            thread.Start();
        }
Example #27
0
        public void Execute(DocumentDatabase database)
        {
            etagSynchronizer    = database.EtagSynchronizer.GetSynchronizer(EtagSynchronizerType.Replicator);
            prefetchingBehavior = database.Prefetcher.GetPrefetchingBehavior(PrefetchingUser.Replicator);

            docDb = database;
            var replicationRequestTimeoutInMs =
                docDb.Configuration.GetConfigurationValue <int>("Raven/Replication/ReplicationRequestTimeout") ??
                60 * 1000;

            httpRavenRequestFactory = new HttpRavenRequestFactory {
                RequestTimeoutInMs = replicationRequestTimeoutInMs
            };

            var task             = new Task(Execute, TaskCreationOptions.LongRunning);
            var disposableAction = new DisposableAction(task.Wait);

            // make sure that the doc db waits for the replication task shutdown
            docDb.ExtensionsState.GetOrAdd(Guid.NewGuid().ToString(), s => disposableAction);
            task.Start();
        }
Example #28
0
        protected void SetupClusterConfiguration(List <DocumentStore> clusterStores, bool enableReplication = true, Dictionary <string, string> databaseSettings = null)
        {
            var clusterStore          = clusterStores[0];
            var requestFactory        = new HttpRavenRequestFactory();
            var replicationRequestUrl = string.Format("{0}/admin/cluster/commands/configuration", clusterStore.Url);
            var replicationRequest    = requestFactory.Create(replicationRequestUrl, HttpMethod.Put, new RavenConnectionStringOptions
            {
                Url = clusterStore.Url
            });

            replicationRequest.Write(RavenJObject.FromObject(new ClusterConfiguration
            {
                EnableReplication = enableReplication,
                DatabaseSettings  = databaseSettings
            }));
            replicationRequest.ExecuteRequest();

            clusterStores.ForEach(store => WaitForDocument(store.DatabaseCommands.ForSystemDatabase(), Constants.Global.ReplicationDestinationsDocumentName));
            using (ForceNonClusterRequests(clusterStores))
            {
                clusterStores.ForEach(store => WaitFor(store.DatabaseCommands, commands =>
                {
                    using (var request = commands.CreateRequest("/configuration/replication", HttpMethod.Get))
                    {
                        var replicationDocumentJson = request.ReadResponseJson() as RavenJObject;
                        if (replicationDocumentJson == null)
                        {
                            return(false);
                        }

                        var replicationDocument = replicationDocumentJson.JsonDeserialization <ReplicationDocument>();
                        return(replicationDocument.Destinations.Count == clusterStores.Count - 1);
                    }
                }));
            }
        }
        private void ReplicateTransformer(string transformerName, ReplicationDestination destination, RavenJObject transformerDefinition, ConcurrentBag <string> failedDestinations, HttpRavenRequestFactory httpRavenRequestFactory)
        {
            var connectionOptions = new RavenConnectionStringOptions
            {
                ApiKey          = destination.ApiKey,
                Url             = destination.Url,
                DefaultDatabase = destination.Database
            };

            if (!String.IsNullOrWhiteSpace(destination.Username) &&
                !String.IsNullOrWhiteSpace(destination.Password))
            {
                connectionOptions.Credentials = new NetworkCredential(destination.Username, destination.Password, destination.Domain ?? string.Empty);
            }

            //databases/{databaseName}/transformers/{*id}
            const string urlTemplate = "{0}/databases/{1}/transformers/{2}";

            if (Uri.IsWellFormedUriString(destination.Url, UriKind.RelativeOrAbsolute) == false)
            {
                const string error = "Invalid destination URL";
                failedDestinations.Add(destination.Url);
                Log.Error(error);
                return;
            }

            var operationUrl       = string.Format(urlTemplate, destination.Url, destination.Database, Uri.EscapeUriString(transformerName));
            var replicationRequest = httpRavenRequestFactory.Create(operationUrl, "PUT", connectionOptions);

            replicationRequest.Write(transformerDefinition);

            try
            {
                replicationRequest.ExecuteRequest();
            }
            catch (Exception e)
            {
                Log.ErrorException("failed to replicate index to: " + destination.Url, e);
                failedDestinations.Add(destination.Url);
            }
        }
        private void ReplicateIndex(string indexName, ReplicationDestination destination, RavenJObject indexDefinition, HttpRavenRequestFactory httpRavenRequestFactory)
        {
            var connectionOptions = new RavenConnectionStringOptions
            {
                ApiKey          = destination.ApiKey,
                Url             = destination.Url,
                DefaultDatabase = destination.Database
            };

            if (!String.IsNullOrWhiteSpace(destination.Username) &&
                !String.IsNullOrWhiteSpace(destination.Password))
            {
                connectionOptions.Credentials = new NetworkCredential(destination.Username, destination.Password, destination.Domain ?? string.Empty);
            }

            const string urlTemplate = "{0}/databases/{1}/indexes/{2}";

            var operationUrl       = string.Format(urlTemplate, destination.Url, destination.Database, Uri.EscapeUriString(indexName));
            var replicationRequest = httpRavenRequestFactory.Create(operationUrl, "PUT", connectionOptions);

            replicationRequest.Write(indexDefinition);

            replicationRequest.ExecuteRequest();
        }