示例#1
0
        public async Task MissingRevisions4()
        {
            var(nodes, leader) = await CreateRaftCluster(3, watcherCluster : true);

            var database = GetDatabaseName();

            await CreateDatabaseInClusterInner(new DatabaseRecord(database), 3, leader.WebUrl, null);

            using (var store = new DocumentStore
            {
                Database = database,
                Urls = new[] { leader.WebUrl }
            }.Initialize())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled               = false,
                        PurgeOnDelete          = false,
                        MinimumRevisionsToKeep = 30
                    }
                };
                long index;
                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configurationJson = EntityToBlittable.ConvertCommandToBlittable(configuration, context);
                    (index, _) = await leader.ServerStore.ModifyDatabaseRevisions(context, database, configurationJson, Guid.NewGuid().ToString());
                }
                await WaitForRaftIndexToBeAppliedInCluster(index, TimeSpan.FromSeconds(15));

                using (var session = store.OpenSession(new SessionOptions {
                    TransactionMode = TransactionMode.ClusterWide
                }))
                {
                    session.Store(new User()
                    {
                        Name = "userT1"
                    }, "users/1");
                    session.Delete("users/2");
                    session.SaveChanges();
                    await WaitForDocumentInClusterAsync <User>(nodes, database, "users/1", null, TimeSpan.FromSeconds(15));
                }

                var revisionCountList = new List <long>();
                foreach (var server in Servers)
                {
                    var documentDatabase = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(database);

                    using (documentDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                        using (context.OpenReadTransaction())
                        {
                            revisionCountList.Add(documentDatabase.DocumentsStorage.RevisionsStorage.GetRevisionsCount(context, "users/1"));
                        }
                }

                Assert.Equal(revisionCountList[0], revisionCountList[1]);
                Assert.Equal(revisionCountList[0], revisionCountList[2]);
            }
        }
示例#2
0
        public static async Task <long> SetupRevisions(Raven.Server.ServerWide.ServerStore serverStore, string database, bool purgeOnDelete = true, long minimumRevisionsToKeep = 123)
        {
            var configuration = new RevisionsConfiguration
            {
                Default = new RevisionsCollectionConfiguration
                {
                    Disabled = false,
                    MinimumRevisionsToKeep = 5,
                },
                Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                {
                    ["Users"] = new RevisionsCollectionConfiguration
                    {
                        Disabled               = false,
                        PurgeOnDelete          = purgeOnDelete,
                        MinimumRevisionsToKeep = minimumRevisionsToKeep
                    },
                    ["Comments"] = new RevisionsCollectionConfiguration
                    {
                        Disabled = true
                    },
                    ["Products"] = new RevisionsCollectionConfiguration
                    {
                        Disabled = true
                    },
                }
            };

            return(await SetupRevisions(serverStore, database, configuration));
        }
示例#3
0
        private async Task SetupRevisions(RavenServer server, string defaultDatabase)
        {
            using (var context = JsonOperationContext.ShortTermSingleUse())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled = false,
                        MinimumRevisionsToKeep = 10,
                    },
                    Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                    {
                        ["Users"] = new RevisionsCollectionConfiguration
                        {
                            Disabled = false,
                            MinimumRevisionsToKeep = 10
                        }
                    }
                };

                var documentDatabase = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(defaultDatabase);

                var res = await documentDatabase.ServerStore.ModifyDatabaseRevisions(context,
                                                                                     defaultDatabase,
                                                                                     DocumentConventions.Default.Serialization.DefaultConverter.ToBlittable(configuration, context), Guid.NewGuid().ToString());

                foreach (var s in Servers)// need to wait for it on all servers
                {
                    documentDatabase = await s.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(defaultDatabase);

                    await documentDatabase.RachisLogIndexNotifications.WaitForIndexNotification(res.Item1, s.ServerStore.Engine.OperationTimeout);
                }
            }
        }
        public CasinoTest(string orchestratorUrl) : base(orchestratorUrl, "CorruptedCasinoTest", "Karmel")
        {
            try
            {
                new BetsIndex().Execute(DocumentStore);
            }
            catch
            {
                // ignore
            }

            // ConfigureExpiration
            var configureExpirationOperationResult = DocumentStore.Maintenance.SendAsync(new ConfigureExpirationOperation(new ExpirationConfiguration
            {
                Disabled             = false,
                DeleteFrequencyInSec = 600
            })).Result;

            // ConfigureRevisions
            var config = new RevisionsConfiguration
            {
                Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                {
                    ["Users"] = new RevisionsCollectionConfiguration
                    {
                        PurgeOnDelete            = true,
                        MinimumRevisionAgeToKeep = TimeSpan.FromSeconds(180)
                    },
                    ["Bets"] = new RevisionsCollectionConfiguration()
                }
            };

            var configureRevisionsOperationResult = DocumentStore.Maintenance.SendAsync(new ConfigureRevisionsOperation(config)).Result;
        }
示例#5
0
        private static async Task SetupRevisionsForTest(RavenServer server, DocumentStore store, string database)
        {
            var configuration = new RevisionsConfiguration
            {
                Default = new RevisionsCollectionConfiguration {
                    Disabled = false, MinimumRevisionsToKeep = int.MaxValue
                },
                Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                {
                    ["Users"] = new RevisionsCollectionConfiguration {
                        Disabled = false, MinimumRevisionsToKeep = int.MaxValue
                    }
                }
            };

            using (var context = JsonOperationContext.ShortTermSingleUse())
            {
                var configurationJson = EntityToBlittable.ConvertCommandToBlittable(configuration, context);
                var(index, _) = await server.ServerStore.ModifyDatabaseRevisions(context, store.Database, configurationJson, Guid.NewGuid().ToString());

                var documentDatabase = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                await documentDatabase.RachisLogIndexNotifications.WaitForIndexNotification(index, server.ServerStore.Engine.OperationTimeout);
            }
        }
示例#6
0
        public void Should_not_allow_having_two_revision_collection_configurations_with_collection_name_that_differs_only_in_casing()
        {
            using (var store = GetDocumentStore())
            {
                var configuration = new RevisionsConfiguration
                {
                    Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                    {
                        {
                            "Users", new RevisionsCollectionConfiguration
                            {
                                PurgeOnDelete = true
                            }
                        },
                        {
                            "users", new RevisionsCollectionConfiguration
                            {
                                MinimumRevisionsToKeep = 5
                            }
                        }
                    }
                };

                var ex = Assert.Throws <RavenException>(() =>
                                                        store.Maintenance.Send(new ConfigureRevisionsOperation(configuration)));


                Assert.Contains("Cannot have two different revision configurations on the same collection", ex.Message);
            }
        }
示例#7
0
        public async Task DeleteDocumentAndRevisions()
        {
            var user = new User {
                Name = "Raven"
            };
            var id = "user/1";

            using (var store = GetDocumentStore())
            {
                await RevisionsHelper.SetupRevisions(Server.ServerStore, store.Database);

                using (var session = store.OpenSession())
                {
                    session.Store(user, id);
                    session.SaveChanges();
                }

                using (var session = store.OpenAsyncSession())
                {
                    user = await session.LoadAsync <User>(id);

                    user.Age = 10;
                    await session.StoreAsync(user);

                    await session.SaveChangesAsync();

                    var metadata = session.Advanced.GetMetadataFor(user);
                    Assert.Equal(DocumentFlags.HasRevisions.ToString(), metadata.GetString(Constants.Documents.Metadata.Flags));
                    var revisions = await session.Advanced.Revisions.GetForAsync <User>(id);

                    Assert.Equal(2, revisions.Count);

                    var configuration = new RevisionsConfiguration()
                    {
                        Default = null
                    };
                    await RevisionsHelper.SetupRevisions(Server.ServerStore, store.Database, configuration);

                    session.Delete(id);
                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenSession())
                {
                    session.Store(user, id);
                    session.SaveChanges();
                    await RevisionsHelper.SetupRevisions(Server.ServerStore, store.Database);
                }

                using (var session = store.OpenAsyncSession())
                {
                    user = await session.LoadAsync <User>(id);

                    var revisions = await session.Advanced.Revisions.GetForAsync <User>(id);

                    Assert.Equal(0, revisions.Count);
                }
            }
        }
示例#8
0
 private void WriteRevisions(RevisionsConfiguration revisions)
 {
     if (revisions == null)
     {
         _writer.WriteNull();
         return;
     }
     _context.Write(_writer, revisions.ToJson());
 }
示例#9
0
        public async Task EnforceEmptyConfigurationWillDeleteAllRevisions()
        {
            using (var store = GetDocumentStore())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration {
                        Disabled = false, MinimumRevisionsToKeep = 10
                    },
                    Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                    {
                        ["Dummy"] = new RevisionsCollectionConfiguration {
                            Disabled = false, MinimumRevisionsToKeep = 10
                        }
                    }
                };

                await store.Maintenance.SendAsync(new ConfigureRevisionsOperation(configuration));

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new Product(), "foo/bar");

                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenAsyncSession())
                {
                    var product = await session.LoadAsync <Product>("foo/bar");

                    var metadata = session.Advanced.GetMetadataFor(product);
                    Assert.Equal((DocumentFlags.HasRevisions).ToString(), metadata[Constants.Documents.Metadata.Flags]);
                    var bar = await session.Advanced.Revisions.GetMetadataForAsync("foo/bar");

                    Assert.Equal(1, bar.Count);
                }

                configuration.Default = null;
                await store.Maintenance.SendAsync(new ConfigureRevisionsOperation(configuration));

                var db = await GetDocumentDatabaseInstanceFor(store);

                using (var token = new OperationCancelToken(db.Configuration.Databases.OperationTimeout.AsTimeSpan, db.DatabaseShutdown))
                    await db.DocumentsStorage.RevisionsStorage.EnforceConfiguration(_ => { }, token);

                using (var session = store.OpenAsyncSession())
                {
                    var product = await session.LoadAsync <Product>("foo/bar");

                    var metadata = session.Advanced.GetMetadataFor(product);
                    Assert.False(metadata.Keys.Contains(Constants.Documents.Metadata.Flags));
                    var foo = await session.Advanced.Revisions.GetMetadataForAsync("foo/bar");

                    Assert.Equal(0, foo.Count);
                }
            }
        }
示例#10
0
        public void InitializeFromDatabaseRecord(DatabaseRecord dbRecord)
        {
            try
            {
                var revisions = dbRecord.Revisions;
                if (revisions == null ||
                    (revisions.Default == null && revisions.Collections.Count == 0))
                {
                    Configuration = null;
                    return;
                }

                if (revisions.Equals(Configuration))
                {
                    return;
                }

                Configuration = revisions;

                using (var tx = _database.DocumentsStorage.Environment.WriteTransaction())
                {
                    foreach (var collection in Configuration.Collections)
                    {
                        if (collection.Value.Disabled)
                        {
                            continue;
                        }
                        EnsureRevisionTableCreated(tx, new CollectionName(collection.Key));
                    }

                    CreateTrees(tx);

                    tx.Commit();
                }

                if (_logger.IsInfoEnabled)
                {
                    _logger.Info("Revisions configuration changed");
                }
            }
            catch (Exception e)
            {
                var msg = "Cannot enable revisions for documents as the revisions configuration " +
                          "in the database record is missing or not valid.";
                _database.NotificationCenter.Add(AlertRaised.Create(
                                                     _database.Name,
                                                     $"Revisions error in {_database.Name}", msg,
                                                     AlertType.RevisionsConfigurationNotValid, NotificationSeverity.Error, _database.Name));
                if (_logger.IsOperationsEnabled)
                {
                    _logger.Operations(msg, e);
                }
            }
        }
示例#11
0
        public async Task ZeroMinimumRevisionsToKeepShouldWork()
        {
            using (var store = GetDocumentStore())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled = false,
                        MinimumRevisionsToKeep = 10
                    },

                    Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                    {
                        ["Users"] = new RevisionsCollectionConfiguration
                        {
                            Disabled = false,
                            MinimumRevisionsToKeep = 0
                        }
                    }
                };

                await store.Maintenance.SendAsync(new ConfigureRevisionsOperation(configuration));

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User(), "foo");

                    await session.StoreAsync(new Product(), "bar");

                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenAsyncSession())
                {
                    var user = await session.LoadAsync <User>("foo");

                    var metadata = session.Advanced.GetMetadataFor(user);
                    Assert.False(metadata.Keys.Contains(Constants.Documents.Metadata.Flags));
                    var foo = await session.Advanced.Revisions.GetMetadataForAsync("foo");

                    Assert.Equal(0, foo.Count);

                    var product = await session.LoadAsync <Product>("bar");

                    metadata = session.Advanced.GetMetadataFor(product);
                    Assert.Equal((DocumentFlags.HasRevisions).ToString(), metadata[Constants.Documents.Metadata.Flags]);
                    var bar = await session.Advanced.Revisions.GetMetadataForAsync("bar");

                    Assert.Equal(1, bar.Count);
                }
            }
        }
示例#12
0
 public RevisionsStorage(DocumentDatabase database, Transaction tx)
 {
     _database             = database;
     _documentsStorage     = _database.DocumentsStorage;
     _logger               = LoggingSource.Instance.GetLogger <RevisionsStorage>(database.Name);
     Operations            = new RevisionsOperations(_database);
     ConflictConfiguration = new RevisionsConfiguration
     {
         Default = new RevisionsCollectionConfiguration
         {
             MinimumRevisionAgeToKeep = TimeSpan.FromDays(45),
             Disabled = false
         }
     };
     CreateTrees(tx);
 }
示例#13
0
        private static async Task ConfigureRevisions()
        {
            var config = new RevisionsConfiguration
            {
                Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                {
                    ["Users"] = new RevisionsCollectionConfiguration
                    {
                        PurgeOnDelete            = true,
                        MinimumRevisionAgeToKeep = TimeSpan.FromSeconds(180)
                    },
                    ["Bets"] = new RevisionsCollectionConfiguration()
                }
            };

            await Store.Maintenance.SendAsync(new ConfigureRevisionsOperation(config)).ConfigureAwait(false);
        }
示例#14
0
            private void WriteRevisions(RevisionsConfiguration revisions)
            {
                if (revisions == null)
                {
                    _writer.WriteNull();
                    return;
                }

                _writer.WriteStartObject();

                _writer.WritePropertyName(nameof(revisions.Default));
                WriteRevisionsCollectionConfiguration(revisions.Default);
                _writer.WriteComma();

                _writer.WritePropertyName(nameof(revisions.Collections));

                if (revisions.Collections == null)
                {
                    _writer.WriteNull();
                }
                else
                {
                    _writer.WriteStartObject();

                    var first = true;
                    foreach (var collection in revisions.Collections)
                    {
                        if (first == false)
                        {
                            _writer.WriteComma();
                        }
                        first = false;

                        _writer.WritePropertyName(collection.Key);
                        WriteRevisionsCollectionConfiguration(collection.Value);
                    }

                    _writer.WriteEndObject();
                }


                _writer.WriteEndObject();
            }
示例#15
0
        public IActionResult Run()
        {
            #region Demo
            #region Step_1
            RevisionsConfiguration myRevisionsConfiguration = new RevisionsConfiguration
            {
                Default = new RevisionsCollectionConfiguration
                {
                    Disabled = false
                }
            };

            ConfigureRevisionsOperation revisionsConfigurationOperation = new ConfigureRevisionsOperation(myRevisionsConfiguration);
            DocumentStoreHolder.Store.Maintenance.Send(revisionsConfigurationOperation);
            #endregion

            List <Company> revisions;

            using (IDocumentSession session = DocumentStoreHolder.Store.OpenSession())
            {
                #region Step_2
                Company company = session.Load <Company>("companies/7-A");

                company.Name = "Name 1";
                session.CountersFor("companies/7-A").Increment("MyCounter", 100);
                session.SaveChanges();

                company.Name  = "Name 2";
                company.Phone = "052-1234-567";
                session.SaveChanges();
                #endregion

                #region Step_3
                revisions = session
                            .Advanced
                            .Revisions
                            .GetFor <Company>("companies/7-A", start: 0, pageSize: 25);
                #endregion
            }
            #endregion

            return(Ok(revisions));
        }
示例#16
0
        public static async Task <long> SetupRevisions(Raven.Server.ServerWide.ServerStore serverStore, string database, Action <RevisionsConfiguration> modifyConfiguration = null)
        {
            var configuration = new RevisionsConfiguration
            {
                Default = new RevisionsCollectionConfiguration
                {
                    Disabled = false,
                    MinimumRevisionsToKeep = 5
                },
                Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                {
                    ["Users"] = new RevisionsCollectionConfiguration
                    {
                        Disabled               = false,
                        PurgeOnDelete          = true,
                        MinimumRevisionsToKeep = 123
                    },
                    ["People"] = new RevisionsCollectionConfiguration
                    {
                        Disabled = false,
                        MinimumRevisionsToKeep = 10
                    },
                    ["Comments"] = new RevisionsCollectionConfiguration
                    {
                        Disabled = true
                    },
                    ["Products"] = new RevisionsCollectionConfiguration
                    {
                        Disabled = true
                    }
                }
            };

            modifyConfiguration?.Invoke(configuration);

            var index = await SetupRevisions(serverStore, database, configuration);

            var documentDatabase = await serverStore.DatabasesLandlord.TryGetOrCreateResourceStore(database);

            await documentDatabase.RachisLogIndexNotifications.WaitForIndexNotification(index, serverStore.Engine.OperationTimeout);

            return(index);
        }
示例#17
0
        public async Task DeleteDocumentWithoutResolvedFlagAfterEnableRevisions()
        {
            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Toli"
                    }, "users/1");
                    session.SaveChanges();
                }

                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled = false,
                        MinimumRevisionsToKeep = 5
                    }
                };
                var database = await GetDatabase(store.Database);

                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configurationJson = DocumentConventions.Default.Serialization.DefaultConverter.ToBlittable(configuration, context);
                    var(index, _) = await database.ServerStore.ModifyDatabaseRevisions(context, store.Database, configurationJson, Guid.NewGuid().ToString());

                    await database.RachisLogIndexNotifications.WaitForIndexNotification(index, database.ServerStore.Engine.OperationTimeout);
                }
                using (var session = store.OpenSession())
                {
                    session.Delete("users/1");
                    session.SaveChanges();
                }

                using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                {
                    context.OpenReadTransaction();
                    var count = database.DocumentsStorage.RevisionsStorage.GetNumberOfRevisionDocuments(context);
                    Assert.Equal(2, count);
                }
            }
        }
示例#18
0
        public async Task DeleteDocumentWithResolvedFlagAfterEnableRevisions()
        {
            using (var store = GetDocumentStore())
            {
                using (var stream = GetDump("RavenDB_15898.1.ravendbdump"))
                {
                    var operation = await store.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), stream);

                    await operation.WaitForCompletionAsync(TimeSpan.FromMinutes(1));
                }
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled = false,
                        MinimumRevisionsToKeep = 5
                    }
                };
                var database = await GetDatabase(store.Database);

                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configurationJson = DocumentConventions.Default.Serialization.DefaultConverter.ToBlittable(configuration, context);
                    var(index, _) = await database.ServerStore.ModifyDatabaseRevisions(context, store.Database, configurationJson, Guid.NewGuid().ToString());

                    await database.RachisLogIndexNotifications.WaitForIndexNotification(index, database.ServerStore.Engine.OperationTimeout);
                }

                using (var session = store.OpenSession())
                {
                    session.Delete("users/1");
                    session.SaveChanges();
                }

                using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                {
                    context.OpenReadTransaction();
                    var count = database.DocumentsStorage.RevisionsStorage.GetNumberOfRevisionDocuments(context);
                    Assert.Equal(2, count);
                }
            }
        }
示例#19
0
        private async Task SetupRevisions(RavenServer server, string defaultDatabase)
        {
            using (var context = JsonOperationContext.ShortTermSingleUse())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Active = true,
                        MinimumRevisionsToKeep = 10,
                    },
                    Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                    {
                        ["Users"] = new RevisionsCollectionConfiguration
                        {
                            Active = true,
                            MinimumRevisionsToKeep = 10
                        }
                    }
                };

                var documentDatabase = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(defaultDatabase);

                var res = await documentDatabase.ServerStore.ModifyDatabaseRevisions(context,
                                                                                     defaultDatabase,
                                                                                     EntityToBlittable.ConvertEntityToBlittable(configuration,
                                                                                                                                new DocumentConventions(),
                                                                                                                                context));

                foreach (var s in Servers)// need to wait for it on all servers
                {
                    documentDatabase = await s.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(defaultDatabase);

                    await documentDatabase.RachisLogIndexNotifications.WaitForIndexNotification(res.Item1);
                }
            }
        }
示例#20
0
        public static async Task SetupRevisions(IDocumentStore store, Raven.Server.ServerWide.ServerStore serverStore, RevisionsConfiguration configuration)
        {
            if (store == null)
            {
                throw new ArgumentNullException(nameof(store));
            }
            if (serverStore == null)
            {
                throw new ArgumentNullException(nameof(serverStore));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            var result = await store.Maintenance.SendAsync(new ConfigureRevisionsOperation(configuration));

            var documentDatabase = await serverStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

            await documentDatabase.RachisLogIndexNotifications.WaitForIndexNotification(result.RaftCommandIndex.Value, serverStore.Engine.OperationTimeout);
        }
示例#21
0
        public async Task MissingRevisions7()
        {
            var(nodes, leader) = await CreateRaftCluster(3, watcherCluster : true);

            var database   = GetDatabaseName();
            var dbCreation = await CreateDatabaseInClusterInner(new DatabaseRecord(database), 2, leader.WebUrl, null);

            using (var storeB = new DocumentStore
            {
                Database = database,
                Urls = new[] { dbCreation.Servers[1].WebUrl },
                Conventions = new DocumentConventions
                {
                    DisableTopologyUpdates = true
                }
            }.Initialize())
                using (var storeA = new DocumentStore
                {
                    Database = database,
                    Urls = new[] { dbCreation.Servers[0].WebUrl },
                    Conventions = new DocumentConventions
                    {
                        DisableTopologyUpdates = true
                    }
                }.Initialize())
                {
                    var configuration = new RevisionsConfiguration
                    {
                        Default = new RevisionsCollectionConfiguration
                        {
                            Disabled               = false,
                            PurgeOnDelete          = false,
                            MinimumRevisionsToKeep = 30
                        }
                    };
                    long index;
                    using (var context = JsonOperationContext.ShortTermSingleUse())
                    {
                        var configurationJson = EntityToBlittable.ConvertCommandToBlittable(configuration, context);
                        (index, _) = await leader.ServerStore.ModifyDatabaseRevisions(context, database, configurationJson, Guid.NewGuid().ToString());
                    }
                    await WaitForRaftIndexToBeAppliedInCluster(index, TimeSpan.FromSeconds(15));

                    await StoreInRegularMode(storeA, 3);

                    await WaitAndAssertForValueAsync(async() =>
                    {
                        var documentDatabase = await dbCreation.Servers[1].ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(database);
                        using (documentDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                            using (context.OpenReadTransaction())
                                return(documentDatabase.DocumentsStorage.RevisionsStorage.GetRevisionsCount(context, "users/1"));
                    }, 3);

                    var result = await leader.ServerStore.SendToLeaderAsync(new DeleteDatabaseCommand(database, Guid.NewGuid().ToString())
                    {
                        HardDelete = true,
                        FromNodes  = new[] { dbCreation.Servers[0].ServerStore.NodeTag },
                    });

                    await WaitForRaftIndexToBeAppliedInCluster(result.Index, TimeSpan.FromSeconds(10));

                    await WaitAndAssertForValueAsync(() =>
                    {
                        var record = storeB.Maintenance.Server.Send(new GetDatabaseRecordOperation(database));
                        return(Task.FromResult(record.DeletionInProgress.Count));
                    }, 0);

                    var breakRepl = await BreakReplication(dbCreation.Servers[1].ServerStore, database);

                    // make member directly, so it can perform cluster tx
                    var record = storeB.Maintenance.Server.Send(new GetDatabaseRecordOperation(database));
                    record.Topology.Members.Add(dbCreation.Servers[0].ServerStore.NodeTag);
                    await storeB.Maintenance.Server.SendAsync(new UpdateDatabaseOperation(record, record.Etag));

                    // have a doc written by cluster tx before we get any replication
                    await StoreInTransactionMode(storeB, 1);

                    breakRepl.Mend();

                    var val = await WaitForValueAsync(async() => await GetMembersCount(storeB, database), 2, 20000);

                    Assert.Equal(2, val);

                    await WaitAndAssertForValueAsync(() =>
                    {
                        var record = storeB.Maintenance.Server.Send(new GetDatabaseRecordOperation(database));
                        return(Task.FromResult(record.DeletionInProgress.Count));
                    }, 0);

                    await WaitAndAssertForValueAsync(async() =>
                    {
                        var documentDatabase = await dbCreation.Servers[0].ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(database);
                        using (documentDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                            using (context.OpenReadTransaction())
                                return(documentDatabase.DocumentsStorage.RevisionsStorage.GetRevisionsCount(context, "users/1"));
                    }, 4);
                }
        }
示例#22
0
        public async Task MissingRevisions()
        {
            var(nodes, leader) = await CreateRaftCluster(3, watcherCluster : true);

            var database = GetDatabaseName();

            await CreateDatabaseInClusterInner(new DatabaseRecord(database), 3, leader.WebUrl, null);

            using (var store = new DocumentStore
            {
                Database = database,
                Urls = new[] { leader.WebUrl }
            }.Initialize())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled               = false,
                        PurgeOnDelete          = false,
                        MinimumRevisionsToKeep = 30
                    }
                };
                long index;
                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configurationJson = EntityToBlittable.ConvertCommandToBlittable(configuration, context);
                    (index, _) = await leader.ServerStore.ModifyDatabaseRevisions(context, database, configurationJson, Guid.NewGuid().ToString());
                }
                await WaitForRaftIndexToBeAppliedInCluster(index, TimeSpan.FromSeconds(15));

                await StoreInTransactionMode(store, 1);
                await StoreInRegularMode(store, 10);
                await DeleteInTransactionMode(store, 1);

                RavenServer testServer = Servers.FirstOrDefault(server => server.ServerStore.IsLeader() == false);

                var result = await DisposeServerAndWaitForFinishOfDisposalAsync(testServer);

                var val = await WaitForValueAsync(async() => await GetMembersCount(store, database), 2, 20000);

                Assert.Equal(2, val);
                testServer = GetNewServer(new ServerCreationOptions
                {
                    DeletePrevious = true,
                    RunInMemory    = false,
                    CustomSettings = new Dictionary <string, string>
                    {
                        [RavenConfiguration.GetKey(x => x.Core.ServerUrls)] = result.Url
                    }
                });

                using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
                {
                    await testServer.ServerStore.Engine.WaitForState(RachisState.Follower, cts.Token);
                }

                await WaitAndAssertForValueAsync(async() => await GetMembersCount(store, database), 3, 20000);

                using (var session = store.OpenSession(new SessionOptions {
                }))
                {
                    session.Store(new User()
                    {
                        Name = "userT"
                    }, "users/1");
                    session.SaveChanges();
                    await WaitForDocumentInClusterAsync <User>(nodes, database, "users/1", null, TimeSpan.FromSeconds(15));
                }

                var documentDatabase = await testServer.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(database);

                {
                    var res = WaitForValue(() =>
                    {
                        using (documentDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                            using (context.OpenReadTransaction())
                                return(documentDatabase.DocumentsStorage.RevisionsStorage.GetRevisionsCount(context, "users/1"));
                    }, 13, 15000);

                    Assert.Equal(13, res);
                }
            }
        }
示例#23
0
        private static async Task <long> SetupRevisions(Raven.Server.ServerWide.ServerStore serverStore, string database, RevisionsConfiguration configuration)
        {
            using (var context = JsonOperationContext.ShortTermSingleUse())
            {
                var configurationJson = EntityToBlittable.ConvertCommandToBlittable(configuration, context);
                var(index, _) = await serverStore.ModifyDatabaseRevisions(context, database, configurationJson);

                return(index);
            }
        }
示例#24
0
        public async Task MissingRevisions3()
        {
            var(nodes, leader) = await CreateRaftCluster(3, watcherCluster : true);

            var database = GetDatabaseName();

            await CreateDatabaseInClusterInner(new DatabaseRecord(database), 3, leader.WebUrl, null);

            using (var store = new DocumentStore
            {
                Database = database,
                Urls = new[] { leader.WebUrl }
            }.Initialize())
            {
                var configuration = new RevisionsConfiguration
                {
                    Default = new RevisionsCollectionConfiguration
                    {
                        Disabled               = false,
                        PurgeOnDelete          = false,
                        MinimumRevisionsToKeep = 30
                    }
                };
                long index;
                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configurationJson = EntityToBlittable.ConvertCommandToBlittable(configuration, context);
                    (index, _) = await leader.ServerStore.ModifyDatabaseRevisions(context, database, configurationJson, Guid.NewGuid().ToString());
                }
                await WaitForRaftIndexToBeAppliedInCluster(index, TimeSpan.FromSeconds(15));

                var testServer = Servers.First(server => server.ServerStore.IsLeader() == false);

                await StoreInTransactionMode(store, 1);
                await StoreInRegularMode(store, 3);
                await DeleteInTransactionMode(store, 1);

                var result = await leader.ServerStore.SendToLeaderAsync(new DeleteDatabaseCommand(database, Guid.NewGuid().ToString())
                {
                    HardDelete = true,
                    FromNodes  = new[] { testServer.ServerStore.NodeTag },
                });

                await WaitForRaftIndexToBeAppliedInCluster(result.Index, TimeSpan.FromSeconds(10));

                var val = await WaitForValueAsync(async() => await GetMembersCount(store, database), 2, 20000);

                Assert.Equal(2, val);

                var delCount = await WaitForValueAsync(() =>
                {
                    var record = store.Maintenance.Server.Send(new GetDatabaseRecordOperation(database));
                    return(record.DeletionInProgress.Count);
                }, 0);

                Assert.Equal(0, delCount);

                await store.Maintenance.Server.SendAsync(new AddDatabaseNodeOperation(database, testServer.ServerStore.NodeTag));

                var documentDatabase = await testServer.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(database);

                await WaitAndAssertForValueAsync(() =>
                {
                    using (documentDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                        using (context.OpenReadTransaction())
                            return(Task.FromResult(documentDatabase.DocumentsStorage.RevisionsStorage.GetRevisionsCount(context, "users/1")));
                }, 5);
            }
        }
示例#25
0
        public async Task ForceRevisionCreationWhenRevisionConfigurationIsSet()
        {
            using (var store = GetDocumentStore())
            {
                // Define revisions settings
                var configuration = new RevisionsConfiguration
                {
                    Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                    {
                        {
                            "Companies", new RevisionsCollectionConfiguration
                            {
                                PurgeOnDelete          = true,
                                MinimumRevisionsToKeep = 5
                            }
                        }
                    }
                };

                var result = await store.Maintenance.SendAsync(new ConfigureRevisionsOperation(configuration));

                var companyId = "";

                using (var session = store.OpenSession())
                {
                    var company = new Company {
                        Name = "HR"
                    };
                    session.Store(company);
                    companyId = company.Id;
                    session.SaveChanges();

                    var revisionsCount = session.Advanced.Revisions.GetFor <Company>(company.Id).Count;
                    Assert.Equal(1, revisionsCount); // one revision because configuration is set

                    session.Advanced.Revisions.ForceRevisionCreationFor <Company>(company);
                    session.SaveChanges();

                    revisionsCount = session.Advanced.Revisions.GetFor <Company>(company.Id).Count;
                    Assert.Equal(1, revisionsCount); // no new revision created - already exists due to configuration settings

                    session.Advanced.Revisions.ForceRevisionCreationFor <Company>(company);
                    session.SaveChanges();

                    company.Name = "HR V2";
                    session.SaveChanges();

                    List <Company> revisions = session.Advanced.Revisions.GetFor <Company>(companyId);
                    revisionsCount = revisions.Count;

                    Assert.Equal(2, revisionsCount);
                    Assert.Equal("HR V2", revisions[0].Name);
                }

                using (var session = store.OpenSession())
                {
                    session.Advanced.Revisions.ForceRevisionCreationFor(companyId);
                    session.SaveChanges();

                    List <Company> revisions      = session.Advanced.Revisions.GetFor <Company>(companyId);
                    var            revisionsCount = revisions.Count;

                    Assert.Equal(2, revisionsCount);
                    Assert.Equal("HR V2", revisions[0].Name);
                }
            }
        }
示例#26
0
        public async Task PlainRevisionsSubscriptionsCompareDocs()
        {
            using (var store = GetDocumentStore())
            {
                var subscriptionId = await store.Subscriptions.CreateAsync <Revision <User> >();

                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configuration = new RevisionsConfiguration
                    {
                        Default = new RevisionsCollectionConfiguration
                        {
                            Active = true,
                            MinimumRevisionsToKeep = 5,
                        },
                        Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                        {
                            ["Users"] = new RevisionsCollectionConfiguration
                            {
                                Active = true
                            },
                            ["Dons"] = new RevisionsCollectionConfiguration
                            {
                                Active = true,
                            }
                        }
                    };

                    await Server.ServerStore.ModifyDatabaseRevisions(context,
                                                                     store.Database,
                                                                     EntityToBlittable.ConvertEntityToBlittable(configuration,
                                                                                                                new DocumentConventions(),
                                                                                                                context));
                }

                for (var j = 0; j < 10; j++)
                {
                    using (var session = store.OpenSession())
                    {
                        session.Store(new User
                        {
                            Name = $"users1 ver {j}",
                            Age  = j
                        }, "users/1");

                        session.Store(new Company()
                        {
                            Name = $"dons1 ver {j}"
                        }, "dons/1");

                        session.SaveChanges();
                    }
                }

                using (var sub = store.Subscriptions.Open <Revision <User> >(new SubscriptionConnectionOptions(subscriptionId)))
                {
                    var mre    = new AsyncManualResetEvent();
                    var names  = new HashSet <string>();
                    var maxAge = -1;
                    GC.KeepAlive(sub.Run(a =>
                    {
                        foreach (var item in a.Items)
                        {
                            var x = item.Result;
                            if (x.Current.Age > maxAge && x.Current.Age > (x.Previous?.Age ?? -1))
                            {
                                names.Add(x.Current?.Name + x.Previous?.Name);
                                maxAge = x.Current.Age;
                            }
                            names.Add(x.Current?.Name + x.Previous?.Name);
                            if (names.Count == 10)
                            {
                                mre.Set();
                            }
                        }
                    }));

                    Assert.True(await mre.WaitAsync(_reasonableWaitTime));
                }
            }
        }
示例#27
0
        public async Task RevisionsSubscriptionsWithCustomScriptCompareDocs()
        {
            using (var store = GetDocumentStore())
            {
                var subscriptionId = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions
                {
                    Query = @"
declare function match(d){
    return d.Current.Age > d.Previous.Age;
}
from Users (Revisions = true) as d
where match(d)
select { Id: id(d.Current), Age: d.Current.Age }
"
                });

                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configuration = new RevisionsConfiguration
                    {
                        Default = new RevisionsCollectionConfiguration
                        {
                            Active = true,
                            MinimumRevisionsToKeep = 5,
                        },
                        Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                        {
                            ["Users"] = new RevisionsCollectionConfiguration
                            {
                                Active = true
                            },
                            ["Dons"] = new RevisionsCollectionConfiguration
                            {
                                Active = true,
                            }
                        }
                    };

                    await Server.ServerStore.ModifyDatabaseRevisions(context,
                                                                     store.Database,
                                                                     EntityToBlittable.ConvertEntityToBlittable(configuration,
                                                                                                                new DocumentConventions(),
                                                                                                                context));
                }

                for (int i = 0; i < 10; i++)
                {
                    for (var j = 0; j < 10; j++)
                    {
                        using (var session = store.OpenSession())
                        {
                            session.Store(new User
                            {
                                Name = $"users{i} ver {j}",
                                Age  = j
                            }, "users/" + i);

                            session.Store(new Company()
                            {
                                Name = $"dons{i} ver {j}"
                            }, "companies/" + i);

                            session.SaveChanges();
                        }
                    }
                }

                using (var sub = store.Subscriptions.Open <Result>(new SubscriptionConnectionOptions(subscriptionId)))
                {
                    var mre    = new AsyncManualResetEvent();
                    var names  = new HashSet <string>();
                    var maxAge = -1;
                    GC.KeepAlive(sub.Run(x =>
                    {
                        foreach (var item in x.Items)
                        {
                            if (item.Result.Age > maxAge)
                            {
                                names.Add(item.Result.Id + item.Result.Age);
                                maxAge = item.Result.Age;
                            }

                            if (names.Count == 9)
                            {
                                mre.Set();
                            }
                        }
                    }));

                    Assert.True(await mre.WaitAsync(_reasonableWaitTime));
                }
            }
        }
示例#28
0
        public async Task RDBCL_801()
        {
            DoNotReuseServer();

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenSession())
                {
                    session.Store(new User
                    {
                        Name = "Karmel"
                    }, "users/1");
                    session.SaveChanges();
                }

                var subscriptionId = await store.Subscriptions.CreateAsync <Revision <User> >();

                using (var context = JsonOperationContext.ShortTermSingleUse())
                {
                    var configuration = new RevisionsConfiguration
                    {
                        Default = new RevisionsCollectionConfiguration
                        {
                            Disabled = false,
                            MinimumRevisionsToKeep = 5,
                        },
                        Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                        {
                            ["Users"] = new RevisionsCollectionConfiguration
                            {
                                Disabled = false
                            },
                            ["Dons"] = new RevisionsCollectionConfiguration
                            {
                                Disabled = false
                            }
                        }
                    };

                    await Server.ServerStore.ModifyDatabaseRevisions(context,
                                                                     store.Database,
                                                                     DocumentConventions.Default.Serialization.DefaultConverter.ToBlittable(configuration,
                                                                                                                                            context), Guid.NewGuid().ToString());
                }

                using (var sub = store.Subscriptions.GetSubscriptionWorker <Revision <User> >(new SubscriptionWorkerOptions(subscriptionId)
                {
                    TimeToWaitBeforeConnectionRetry = TimeSpan.FromSeconds(5)
                }))
                {
                    GC.KeepAlive(sub.Run(x =>
                    {
                    }));

                    var acks = 0;
                    await Task.Delay(5000);

                    using (Server.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context))
                        using (context.OpenReadTransaction())
                        {
                            foreach (var entry in Server.ServerStore.Engine.LogHistory.GetHistoryLogs(context))
                            {
                                var type = entry[nameof(RachisLogHistory.LogHistoryColumn.Type)].ToString();
                                if (type == nameof(AcknowledgeSubscriptionBatchCommand))
                                {
                                    acks++;
                                }
                            }
                        }

                    Assert.True(acks < 50, $"{acks}");
                }
            }
        }
示例#29
0
        protected static async Task CanExportWithPulsatingReadTransaction_ActualTest(int numberOfUsers, int numberOfCountersPerUser, int numberOfRevisionsPerDocument,
                                                                                     int numberOfOrders, int deleteUserFactor, DocumentStore storeToExport, string file, DocumentStore storeToImport, string fileAfterDeletions,
                                                                                     DocumentStore storeToAfterDeletions)
        {
            if (numberOfRevisionsPerDocument > 0)
            {
                var configuration = new RevisionsConfiguration {
                    Default = new RevisionsCollectionConfiguration {
                        Disabled = false, MinimumRevisionsToKeep = 10
                    }
                };

                await storeToExport.Maintenance.SendAsync(new ConfigureRevisionsOperation(configuration));
            }

            using (var bulk = storeToExport.BulkInsert())
            {
                for (int i = 0; i < Math.Max(numberOfUsers, numberOfOrders); i++)
                {
                    if (i < numberOfUsers)
                    {
                        bulk.Store(new User(), "users/" + i);
                    }

                    if (i < numberOfOrders)
                    {
                        bulk.Store(new Order(), "orders/" + i);
                    }
                }
            }

            if (numberOfRevisionsPerDocument > 2)
            {
                for (int j = 0; j < numberOfRevisionsPerDocument; j++)
                {
                    using (var bulk = storeToExport.BulkInsert())
                    {
                        for (int i = 0; i < Math.Max(numberOfUsers, numberOfOrders); i++)
                        {
                            if (i < numberOfUsers)
                            {
                                bulk.Store(new User()
                                {
                                    Name = i + " " + j
                                }, "users/" + i);
                            }

                            if (i < numberOfOrders)
                            {
                                bulk.Store(new Order()
                                {
                                    Company = i + " " + j
                                }, "orders/" + i);
                            }
                        }
                    }
                }
            }

            using (var session = storeToExport.OpenSession())
            {
                for (int i = 0; i < numberOfUsers; i++)
                {
                    for (int j = 0; j < numberOfCountersPerUser; j++)
                    {
                        session.CountersFor("users/" + i).Increment("counter/" + j, 100);
                    }
                }

                session.SaveChanges();
            }

            var originalStats = await storeToExport.Maintenance.SendAsync(new GetStatisticsOperation());

            var options = new DatabaseSmugglerExportOptions();

            var operation = await storeToExport.Smuggler.ExportAsync(options, file);

            var result = await operation.WaitForCompletionAsync(TimeSpan.FromMinutes(2));

            SmugglerResult.SmugglerProgress progress = ((SmugglerResult)result).Progress as SmugglerResult.SmugglerProgress;

            Assert.Equal(originalStats.CountOfDocuments, progress.Documents.ReadCount);
            Assert.Equal(originalStats.CountOfCounterEntries, progress.Counters.ReadCount);
            Assert.Equal(originalStats.CountOfRevisionDocuments, progress.RevisionDocuments.ReadCount);

            operation = await storeToImport.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), file);

            await operation.WaitForCompletionAsync(TimeSpan.FromMinutes(2));

            var stats = await storeToImport.Maintenance.SendAsync(new GetStatisticsOperation());

            Assert.Equal(numberOfUsers + numberOfOrders, stats.CountOfDocuments);
            Assert.Equal(numberOfUsers, stats.CountOfCounterEntries);

            var expectedNumberOfRevisions = (numberOfUsers + numberOfOrders) * numberOfRevisionsPerDocument;

            if (numberOfCountersPerUser > 0)
            {
                // if we added counters then additional revisions were created
                expectedNumberOfRevisions += numberOfUsers;
            }

            Assert.Equal(expectedNumberOfRevisions, stats.CountOfRevisionDocuments);

            // deleting some docs

            var deletedUsers = 0;

            using (var session = storeToExport.OpenSession())
            {
                for (int i = 0; i < numberOfUsers; i++)
                {
                    if (i % deleteUserFactor != 0)
                    {
                        continue;
                    }

                    session.Delete("users/" + i);

                    deletedUsers++;
                }

                session.SaveChanges();
            }

            // import to new db

            var originalStatsAfterDeletions = await storeToExport.Maintenance.SendAsync(new GetStatisticsOperation());

            options.OperateOnTypes |= DatabaseItemType.Tombstones;

            operation = await storeToExport.Smuggler.ExportAsync(options, fileAfterDeletions);

            result = await operation.WaitForCompletionAsync(TimeSpan.FromMinutes(2));

            progress = ((SmugglerResult)result).Progress as SmugglerResult.SmugglerProgress;

            Assert.Equal(originalStatsAfterDeletions.CountOfDocuments, progress.Documents.ReadCount);
            Assert.Equal(originalStatsAfterDeletions.CountOfCounterEntries, progress.Counters.ReadCount);
            Assert.Equal(originalStatsAfterDeletions.CountOfRevisionDocuments, progress.RevisionDocuments.ReadCount);
            Assert.Equal(originalStatsAfterDeletions.CountOfTombstones, progress.Tombstones.ReadCount);

            var importOptions = new DatabaseSmugglerImportOptions();

            importOptions.OperateOnTypes |= DatabaseItemType.Tombstones;

            operation = await storeToAfterDeletions.Smuggler.ImportAsync(importOptions, fileAfterDeletions);

            await operation.WaitForCompletionAsync(TimeSpan.FromMinutes(2));

            var statsAfterDeletions = await storeToAfterDeletions.Maintenance.SendAsync(new GetStatisticsOperation());

            Assert.Equal(numberOfUsers - deletedUsers + numberOfOrders, statsAfterDeletions.CountOfDocuments);
            Assert.Equal(numberOfUsers - deletedUsers, statsAfterDeletions.CountOfCounterEntries);
            Assert.Equal(expectedNumberOfRevisions, statsAfterDeletions.CountOfRevisionDocuments);
            Assert.Equal(deletedUsers, statsAfterDeletions.CountOfTombstones);
        }
示例#30
0
        private static async Task <long> SetupRevisions(Raven.Server.ServerWide.ServerStore serverStore, string database, RevisionsConfiguration configuration)
        {
            using (var context = JsonOperationContext.ShortTermSingleUse())
            {
                var configurationJson = EntityToBlittable.ConvertEntityToBlittable(configuration, DocumentConventions.Default, context);
                (long etag, _) = await serverStore.ModifyDatabaseRevisions(context, database, configurationJson);

                return(etag);
            }
        }