diff --git a/src/Raven.Client/Documents/Indexes/AbstractIndexCreationTask.cs b/src/Raven.Client/Documents/Indexes/AbstractIndexCreationTask.cs index 9e183ce68d08..fc8195632e11 100644 --- a/src/Raven.Client/Documents/Indexes/AbstractIndexCreationTask.cs +++ b/src/Raven.Client/Documents/Indexes/AbstractIndexCreationTask.cs @@ -267,6 +267,8 @@ public interface IAbstractIndexCreationTask DocumentConventions Conventions { get; set; } + SearchEngineType? SearchEngineType { get; } + IndexDefinition CreateIndexDefinition(); void Execute(IDocumentStore store, DocumentConventions conventions = null, string database = null); diff --git a/src/Raven.Client/Documents/Indexes/IndexCreation.cs b/src/Raven.Client/Documents/Indexes/IndexCreation.cs index be5c2d05c22c..7b6d3f0408a6 100644 --- a/src/Raven.Client/Documents/Indexes/IndexCreation.cs +++ b/src/Raven.Client/Documents/Indexes/IndexCreation.cs @@ -103,6 +103,10 @@ internal static IndexDefinition[] CreateIndexesToAdd(IEnumerable async (dispatch: AppDispatch, getState: () => RootState) => { - const firstTime = selectEssentialStats(getState()).status === "idle"; + const firstTime = + selectEssentialStats(getState()).status === "idle" || db.name !== getState().statistics.databaseName; if (firstTime) { dispatch(initForDatabase(db.name, DatabaseUtils.getLocations(db))); diff --git a/test/RachisTests/DatabaseCluster/AtomicClusterReadWriteTests.cs b/test/RachisTests/DatabaseCluster/AtomicClusterReadWriteTests.cs index 7d00a4712237..0b9f3830bc3d 100644 --- a/test/RachisTests/DatabaseCluster/AtomicClusterReadWriteTests.cs +++ b/test/RachisTests/DatabaseCluster/AtomicClusterReadWriteTests.cs @@ -338,13 +338,7 @@ public async Task CanRestoreAfterRecreation(Options options) var backupStatus3 = await source.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId)); await backupStatus3.WaitForCompletionAsync(TimeSpan.FromMinutes(5)); - var backupDir = Directory.GetDirectories(backupPath).First(); - var files = Directory.GetFiles(backupDir) - .Where(BackupUtils.IsBackupFile) - .OrderBackups() - .ToArray(); - - Assert.Equal(3, files.Length); + var files = await Backup.GetBackupFilesAndAssertCountAsync(backupPath, 3, source.Database, backupStatus3.Id); var smugglerOptions = new DatabaseSmugglerImportOptions(); DatabaseSmuggler.ConfigureOptionsForIncrementalImport(smugglerOptions); @@ -458,6 +452,8 @@ public async Task ClusterWideTransaction_WhenRestoreFromIncrementalBackupAfterSt var backupStatus2 = await source.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId)); await backupStatus2.WaitForCompletionAsync(TimeSpan.FromMinutes(5)); + await Backup.GetBackupFilesAndAssertCountAsync(backupPath, 2, source.Database, backupStatus2.Id); + await documentStore.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(), Directory.GetDirectories(backupPath).First()); } @@ -521,6 +517,8 @@ public async Task ClusterWideTransaction_WhenRestoreFromIncrementalBackupAfterSt var backupStatus2 = await source.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId)); await backupStatus2.WaitForCompletionAsync(TimeSpan.FromMinutes(5)); + await Backup.GetBackupFilesAndAssertCountAsync(backupPath, 2, source.Database, backupStatus2.Id); + await documentStore.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(), Directory.GetDirectories(backupPath).First()); } diff --git a/test/SlowTests/Cluster/ClusterTransactionTests.cs b/test/SlowTests/Cluster/ClusterTransactionTests.cs index a83b62814cce..536cc3825d97 100644 --- a/test/SlowTests/Cluster/ClusterTransactionTests.cs +++ b/test/SlowTests/Cluster/ClusterTransactionTests.cs @@ -1396,13 +1396,13 @@ public async Task ClusterWideTransaction_WhenStoreDocWithEmptyStringId_ShouldThr { TransactionMode = TransactionMode.ClusterWide }); - + var entity = new User { Id = id }; await session.StoreAsync(entity); await session.SaveChangesAsync(); }); - Assert.True(ContainsRachisException(e)); - + Assert.True(ContainsRachisException(e), e.ToString()); + static bool ContainsRachisException(Exception e) { while (true) @@ -1411,7 +1411,7 @@ static bool ContainsRachisException(Exception e) return true; if (e is AggregateException ae) return ae.InnerExceptions.Any(ex => ContainsRachisException(ex)); - + if (e.InnerException == null) return false; e = e.InnerException; diff --git a/test/SlowTests/Issues/RavenDB-21050.cs b/test/SlowTests/Issues/RavenDB-21050.cs index 7025a076e905..b0c1f08209ce 100644 --- a/test/SlowTests/Issues/RavenDB-21050.cs +++ b/test/SlowTests/Issues/RavenDB-21050.cs @@ -56,6 +56,8 @@ public async Task ClusterWideTransaction_WhenRestoreFromIncrementalBackupAfterSt path = Directory.GetDirectories(backupPath).First(p => p.Contains($"${shardNumber}")); } + await Backup.GetBackupFilesAndAssertCountAsync(path, 2, source.Database, backupStatus2.Id); + var restoreConfig = new RestoreBackupConfiguration { BackupLocation = path, DatabaseName = destination.Database }; using (Backup.RestoreDatabase(destination, restoreConfig)) { diff --git a/test/SlowTests/Issues/RavenDB_22750.cs b/test/SlowTests/Issues/RavenDB_22750.cs new file mode 100644 index 000000000000..016f14ecb4bd --- /dev/null +++ b/test/SlowTests/Issues/RavenDB_22750.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading.Tasks; +using FastTests; +using Raven.Client.Documents; +using SlowTests.Core.Utils.Entities; +using SlowTests.Core.Utils.Indexes; +using Tests.Infrastructure; +using Xunit; +using Xunit.Abstractions; + +namespace SlowTests.Issues; + +public class RavenDB_22750 : RavenTestBase +{ + public RavenDB_22750(ITestOutputHelper output) : base(output) + { + } + + [RavenFact(RavenTestCategory.Querying)] + public async Task IndexTimestamp_And_LastQueryTime_Needs_To_Have_DateTimeKind_Specified() + { + using (var store = GetDocumentStore()) + { + await new Companies_ByEmployeeLastName().ExecuteAsync(store); + + Indexes.WaitForIndexing(store); + + using (var session = store.OpenAsyncSession()) + { + await session.Query() + .Statistics(out var stats) + .ToListAsync(); + + Assert.Equal(DateTimeKind.Utc, stats.IndexTimestamp.Kind); + Assert.Equal(DateTimeKind.Utc, stats.LastQueryTime.Kind); + } + } + } +} diff --git a/test/SlowTests/Issues/RavenDB_22753.cs b/test/SlowTests/Issues/RavenDB_22753.cs new file mode 100644 index 000000000000..0d1346c22eb6 --- /dev/null +++ b/test/SlowTests/Issues/RavenDB_22753.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Linq; +using FastTests; +using Raven.Client; +using Raven.Client.Documents.Indexes; +using Raven.Client.Documents.Operations.Indexes; +using Raven.Tests.Core.Utils.Entities; +using Tests.Infrastructure; +using Xunit; +using Xunit.Abstractions; + +namespace SlowTests.Issues; + +public class RavenDB_22753 : RavenTestBase +{ + public RavenDB_22753(ITestOutputHelper output) : base(output) + { + } + + [RavenFact(RavenTestCategory.ClientApi | RavenTestCategory.Indexes)] + public void MustSendSearchEngineType() + { + using var store = GetDocumentStore(); + + IndexCreation.CreateIndexes(new [] + { + new Users_ByName() + }, store); + + IndexDefinition[] indexDefinitions = store.Maintenance.Send(new GetIndexesOperation(0, 1)); + + Assert.Contains(Constants.Configuration.Indexes.IndexingStaticSearchEngineType, (IDictionary) indexDefinitions[0].Configuration); + Assert.Equal("Corax", indexDefinitions[0].Configuration[Constants.Configuration.Indexes.IndexingStaticSearchEngineType]); + } + + private class Users_ByName : AbstractIndexCreationTask + { + public Users_ByName() + { + Map = users => from u in users select new { Name = u.Name, LastName = u.LastName }; + + SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax; + } + } +} diff --git a/test/SlowTests/Server/Documents/Notifications/ChangesTests.cs b/test/SlowTests/Server/Documents/Notifications/ChangesTests.cs index 4edf10e50b24..ebdaf27ca160 100644 --- a/test/SlowTests/Server/Documents/Notifications/ChangesTests.cs +++ b/test/SlowTests/Server/Documents/Notifications/ChangesTests.cs @@ -163,9 +163,9 @@ public async Task CanCreateMultipleNotificationsOnSingleConnection() public async Task NotificationOnWrongDatabase_ShouldNotCrashServer() { using (var store = GetDocumentStore()) - { - var taskObservable = store.Changes("does-not-exists"); - Assert.True( await Assert.ThrowsAsync(async () => await taskObservable.EnsureConnectedNow()).WaitWithoutExceptionAsync(TimeSpan.FromSeconds(15))); + { + var taskObservable = store.Changes("does-not-exists"); + Assert.True(await Assert.ThrowsAsync(async () => await taskObservable.EnsureConnectedNow()).WaitWithoutExceptionAsync(TimeSpan.FromSeconds(15))); // ensure the db still works store.Maintenance.Send(new GetStatisticsOperation()); @@ -211,26 +211,26 @@ public async Task CanGetNotificationAboutDocumentsStartingWith() var taskObservable = store.Changes(); await taskObservable.EnsureConnectedNow(); var observableWithTask = taskObservable.ForDocumentsStartingWith("users/"); - + observableWithTask.Subscribe(x => { if (x.Type == DocumentChangeTypes.Put) list.Add(x.Id); }); await observableWithTask.EnsureSubscribedNow(); - + using (var session = store.OpenSession()) { session.Store(new User(), "users/1"); session.SaveChanges(); } - + using (var session = store.OpenSession()) { session.Store(new User(), "differentDocumentPrefix/1"); session.SaveChanges(); } - + using (var session = store.OpenSession()) { session.Store(new User(), "users/2"); @@ -242,7 +242,7 @@ public async Task CanGetNotificationAboutDocumentsStartingWith() Assert.Contains("users/2", list); } } - + [Fact] public async Task CanGetNotificationAboutDocumentsFromCollection() { @@ -252,26 +252,26 @@ public async Task CanGetNotificationAboutDocumentsFromCollection() var taskObservable = store.Changes(); await taskObservable.EnsureConnectedNow(); var observableWithTask = taskObservable.ForDocumentsInCollection("users"); - + observableWithTask.Subscribe(x => { if (x.Type == DocumentChangeTypes.Put) list.Add(x.Id); }); await observableWithTask.EnsureSubscribedNow(); - + using (var session = store.OpenSession()) { session.Store(new User(), "users/1"); session.SaveChanges(); } - + using (var session = store.OpenSession()) { session.Store(new Employee(), "employees/1"); session.SaveChanges(); } - + using (var session = store.OpenSession()) { session.Store(new User(), "users/2"); @@ -359,83 +359,90 @@ await Assert.ThrowsAsync(async () => await store.Maintenance.Server.SendAsync(new CreateDatabaseOperation(new DatabaseRecord(newDatabaseName))); - using (var session = store.OpenAsyncSession(newDatabaseName)) + try { - await session.StoreAsync(new User + using (var session = store.OpenAsyncSession(newDatabaseName)) { - Name = oldName - }, "users/1"); - await session.SaveChangesAsync(); - } - - using (await store.AggressivelyCacheForAsync(TimeSpan.MaxValue, database: newDatabaseName)) - using (var session = store.OpenAsyncSession(newDatabaseName)) - { - var loaded = await session.LoadAsync("users/1"); - Assert.Equal(oldName, loaded.Name); - } - - using (var session = store.OpenAsyncSession(newDatabaseName)) - { - var loaded = await session.LoadAsync("users/1"); - loaded.Name = newName; - await session.SaveChangesAsync(); - } + await session.StoreAsync(new User + { + Name = oldName + }, "users/1"); + await session.SaveChangesAsync(); + } - var value = await WaitForValueAsync(async () => - { using (await store.AggressivelyCacheForAsync(TimeSpan.MaxValue, database: newDatabaseName)) using (var session = store.OpenAsyncSession(newDatabaseName)) { var loaded = await session.LoadAsync("users/1"); - return loaded.Name; + Assert.Equal(oldName, loaded.Name); } - }, newName); - - Assert.Equal(newName, value); - await store.Maintenance.Server.SendAsync(new DeleteDatabasesOperation(newDatabaseName, hardDelete: true)); + using (var session = store.OpenAsyncSession(newDatabaseName)) + { + var loaded = await session.LoadAsync("users/1"); + loaded.Name = newName; + await session.SaveChangesAsync(); + } - var exception = await WaitForValueAsync(async () => - { - try + var value = await WaitForValueAsync(async () => { using (await store.AggressivelyCacheForAsync(TimeSpan.MaxValue, database: newDatabaseName)) + using (var session = store.OpenAsyncSession(newDatabaseName)) { + var loaded = await session.LoadAsync("users/1"); + return loaded.Name; } + }, newName); - return false; - } - catch (DatabaseDoesNotExistException) + Assert.Equal(newName, value); + + await store.Maintenance.Server.SendAsync(new DeleteDatabasesOperation(newDatabaseName, hardDelete: true)); + + var exception = await WaitForValueAsync(async () => { - return true; - } - }, true); + try + { + using (await store.AggressivelyCacheForAsync(TimeSpan.MaxValue, database: newDatabaseName)) + { + } - Assert.True(exception); + return false; + } + catch (DatabaseDoesNotExistException) + { + return true; + } + }, true); - await store.Maintenance.Server.SendAsync(new CreateDatabaseOperation(new DatabaseRecord(newDatabaseName))); + Assert.True(exception); - using (var session = store.OpenAsyncSession(newDatabaseName)) - { - await session.StoreAsync(new User - { - Name = oldName - }, "users/1"); - await session.SaveChangesAsync(); - } + await store.Maintenance.Server.SendAsync(new CreateDatabaseOperation(new DatabaseRecord(newDatabaseName))); - value = await WaitForValueAsync(async () => - { - using (await store.AggressivelyCacheForAsync(TimeSpan.MaxValue, database: newDatabaseName)) using (var session = store.OpenAsyncSession(newDatabaseName)) { - var loaded = await session.LoadAsync("users/1"); - return loaded.Name; + await session.StoreAsync(new User + { + Name = oldName + }, "users/1"); + await session.SaveChangesAsync(); } - }, oldName); - Assert.Equal(oldName, value); + value = await WaitForValueAsync(async () => + { + using (await store.AggressivelyCacheForAsync(TimeSpan.MaxValue, database: newDatabaseName)) + using (var session = store.OpenAsyncSession(newDatabaseName)) + { + var loaded = await session.LoadAsync("users/1"); + return loaded.Name; + } + }, oldName); + + Assert.Equal(oldName, value); + } + finally + { + await store.Maintenance.Server.SendAsync(new DeleteDatabasesOperation(newDatabaseName, hardDelete: true)); + } } } diff --git a/test/Tests.Infrastructure/ClusterTestBase.cs b/test/Tests.Infrastructure/ClusterTestBase.cs index faca61a3fbe2..f528902b1e2b 100644 --- a/test/Tests.Infrastructure/ClusterTestBase.cs +++ b/test/Tests.Infrastructure/ClusterTestBase.cs @@ -529,7 +529,8 @@ public List GetDocumentStores(List nodes, string dat Certificate = certificate, Conventions = { - DisableTopologyUpdates = disableTopologyUpdates + DisableTopologyUpdates = disableTopologyUpdates, + DisposeCertificate = false } }; store.Initialize(); @@ -781,7 +782,7 @@ protected async Task DisposeAndRemoveServer(RavenServer serverToDispose) bool? shouldRunInMemory = null, int? leaderIndex = null, bool useSsl = false, - IDictionary customSettings = null, + IDictionary commonCustomSettings = null, List> customSettingsList = null, bool watcherCluster = false, bool useReservedPorts = false, @@ -805,12 +806,16 @@ protected async Task DisposeAndRemoveServer(RavenServer serverToDispose) for (var i = 0; i < numberOfNodes; i++) { + IDictionary customSettings; if (customSettingsList == null) { - customSettings ??= new Dictionary(DefaultClusterSettings) + customSettings = new Dictionary(commonCustomSettings ?? DefaultClusterSettings); + + var electionKey = RavenConfiguration.GetKey(x => x.Cluster.ElectionTimeout); + if (customSettings.ContainsKey(electionKey) == false) { - [RavenConfiguration.GetKey(x => x.Cluster.ElectionTimeout)] = _electionTimeoutInMs.ToString(), - }; + customSettings[electionKey] = _electionTimeoutInMs.ToString(); + } } else { diff --git a/test/Tests.Infrastructure/RavenTestBase.Backup.cs b/test/Tests.Infrastructure/RavenTestBase.Backup.cs index b078c0b1f8fe..117885baf46e 100644 --- a/test/Tests.Infrastructure/RavenTestBase.Backup.cs +++ b/test/Tests.Infrastructure/RavenTestBase.Backup.cs @@ -648,6 +648,25 @@ internal async Task HoldBackupExecutionIfNeededAndInvoke(PeriodicBackupRunner.Te tcs.TrySetResult(null); } } + + public async Task GetBackupFilesAndAssertCountAsync(string backupPath, int count, string databaseName, long backupOpId) + { + var backupDir = Directory.GetDirectories(backupPath).First(); + var filesEnumerable = Directory.GetFiles(backupDir) + .Where(Raven.Client.Documents.Smuggler.BackupUtils.IsBackupFile); + var files = Raven.Client.Documents.Smuggler.BackupUtils.OrderBackups(filesEnumerable).ToArray(); + + if (files.Length != count) + { + using var context = JsonOperationContext.ShortTermSingleUse(); + var database = await _parent.GetDatabase(databaseName); + var operation = database.Operations.GetOperation(backupOpId); + var jsonOperation = context.ReadObject(operation.ToJson(), "backup operation"); + Assert.Fail($"Expected {count} backup files but found {files.Length}.\n{string.Join("\n", files)}\n{jsonOperation}"); + } + + return files; + } public async Task RunBackupForDatabaseModeAsync(RavenServer server, PeriodicBackupConfiguration config, IDocumentStore store, RavenDatabaseMode databaseMode, bool isFullBackup = true, long? taskId = null) {