Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 4 additions & 32 deletions src/ServiceControl.Audit.Persistence.RavenDB/DatabaseSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using Raven.Client.Exceptions;
using Raven.Client.ServerWide;
using Raven.Client.ServerWide.Operations;
using Raven.Client.ServerWide.Operations.Configuration;
using Indexes;
using ServiceControl.RavenDB;
using SagaAudit;
Expand All @@ -24,8 +23,6 @@ public async Task Execute(IDocumentStore documentStore, CancellationToken cancel
{
await CreateDatabase(documentStore, configuration.Name, cancellationToken);

await UpdateDatabaseSettings(documentStore, configuration.Name, cancellationToken);

await CreateIndexes(documentStore, configuration.EnableFullTextSearch, cancellationToken);

await StartupChecks.WarnIfIndexesUseCorax(documentStore, configuration.Name, cancellationToken);
Expand All @@ -45,8 +42,10 @@ async Task CreateDatabase(IDocumentStore documentStore, string databaseName, Can
var databaseRecord = new DatabaseRecord(databaseName);

// New databases use Lucene: smaller indexes, lower memory usage and faster for our index definitions.
// Existing databases keep the engine they were created with, see UpdateDatabaseSettings.
SetSearchEngineType(databaseRecord, SearchEngineType.Lucene);
// The settings of an existing database are left to the operator. An index keeps the engine it was
// built with until it is rebuilt, so the database default does not change existing indexes.
databaseRecord.Settings["Indexing.Auto.SearchEngineType"] = nameof(SearchEngineType.Lucene);
databaseRecord.Settings["Indexing.Static.SearchEngineType"] = nameof(SearchEngineType.Lucene);

await documentStore.Maintenance.Server.SendAsync(new CreateDatabaseOperation(databaseRecord), cancellationToken);
}
Expand All @@ -57,23 +56,6 @@ async Task CreateDatabase(IDocumentStore documentStore, string databaseName, Can
}
}

async Task UpdateDatabaseSettings(IDocumentStore documentStore, string databaseName, CancellationToken cancellationToken)
{
var databaseRecord = await documentStore.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(databaseName), cancellationToken) ?? throw new InvalidOperationException($"Database '{databaseName}' does not exist.");

// Existing databases keep their configured search engine. Changing it would trigger a full rebuild of all
// indexes, which can take a long time and a lot of resources on large databases. Databases created before the
// search engine was pinned explicitly get Corax, which was the default at the time.
if (!SetSearchEngineType(databaseRecord, SearchEngineType.Corax))
{
return;
}

await documentStore.Maintenance.ForDatabase(databaseName).SendAsync(new PutDatabaseSettingsOperation(databaseName, databaseRecord.Settings), cancellationToken);
await documentStore.Maintenance.Server.SendAsync(new ToggleDatabasesStateOperation(databaseName, true), cancellationToken);
await documentStore.Maintenance.Server.SendAsync(new ToggleDatabasesStateOperation(databaseName, false), cancellationToken);
}

public static async Task DeleteLegacySagaDetailsIndex(IDocumentStore documentStore, CancellationToken cancellationToken = default)
{
// If the SagaDetailsIndex exists but does not have a .Take(50000), then we remove the current SagaDetailsIndex and
Expand Down Expand Up @@ -121,16 +103,6 @@ async Task ConfigureExpiration(IDocumentStore documentStore, CancellationToken c
await documentStore.Maintenance.SendAsync(new ConfigureExpirationOperation(expirationConfig), cancellationToken);
}

bool SetSearchEngineType(DatabaseRecord database, SearchEngineType searchEngineType)
{
var updated = false;

updated |= database.Settings.TryAdd("Indexing.Auto.SearchEngineType", searchEngineType.ToString());
updated |= database.Settings.TryAdd("Indexing.Static.SearchEngineType", searchEngineType.ToString());

return updated;
}

internal const string MessagesViewIndexWithFulltextSearchName = "MessagesViewIndexWithFullTextSearch";
internal const string SagaDetailsIndexName = "SagaDetailsIndex";
internal const string MessagesViewIndexName = "MessagesViewIndex";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace ServiceControl.Audit.Persistence.Tests;

using System;
using System.Threading.Tasks;
using NUnit.Framework;
using Persistence.RavenDB;
using Raven.Client.Documents.Indexes;
using Raven.Client.ServerWide.Operations;
using Raven.Client.ServerWide.Operations.Configuration;

[TestFixture]
class DatabaseSettingsTests : PersistenceTestFixture
{
[Test]
public async Task New_database_should_use_lucene()
{
var record = await configuration.DocumentStore.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(configuration.DocumentStore.Database), TestTimeoutCancellationToken);

Assert.That(record.Settings, Does.ContainKey("Indexing.Auto.SearchEngineType").WithValue(nameof(SearchEngineType.Lucene)));
Assert.That(record.Settings, Does.ContainKey("Indexing.Static.SearchEngineType").WithValue(nameof(SearchEngineType.Lucene)));
}

[Test]
public async Task Setup_should_not_add_search_engine_settings_to_an_existing_database()
{
var store = configuration.DocumentStore;
var databaseName = store.Database;

// RavenDB Studio removes a database setting whose value equals the server default. Versions 6.20.0 to 6.21.2
// then added Corax back at every start, also in maintenance mode, and undid the operator's choice.
await store.Maintenance.ForDatabase(databaseName).SendAsync(new PutDatabaseSettingsOperation(databaseName, []), TestTimeoutCancellationToken);
await store.Maintenance.Server.SendAsync(new ToggleDatabasesStateOperation(databaseName, true), TestTimeoutCancellationToken);
await store.Maintenance.Server.SendAsync(new ToggleDatabasesStateOperation(databaseName, false), TestTimeoutCancellationToken);

var databaseConfiguration = new DatabaseConfiguration(databaseName, 60, true, TimeSpan.FromDays(1), 100_000, 20, 20, new ServerConfiguration(store.Urls[0]), TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
await new DatabaseSetup(databaseConfiguration).Execute(store, TestTimeoutCancellationToken);

var record = await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(databaseName), TestTimeoutCancellationToken);

Assert.That(record.Settings, Does.Not.ContainKey("Indexing.Auto.SearchEngineType"));
Assert.That(record.Settings, Does.Not.ContainKey("Indexing.Static.SearchEngineType"));
}
}
32 changes: 2 additions & 30 deletions src/ServiceControl.Persistence.RavenDB/DatabaseSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace ServiceControl.Persistence.RavenDB
using Raven.Client.Exceptions;
using Raven.Client.ServerWide;
using Raven.Client.ServerWide.Operations;
using Raven.Client.ServerWide.Operations.Configuration;
using ServiceControl.RavenDB;

class DatabaseSetup(RavenPersisterSettings settings, IDocumentStore documentStore)
Expand All @@ -18,9 +17,6 @@ public async Task Execute(CancellationToken cancellationToken = default)
await CreateDatabase(settings.DatabaseName, cancellationToken);
await CreateDatabase(settings.ThroughputDatabaseName, cancellationToken);

await UpdateDatabaseSettings(settings.DatabaseName, cancellationToken);
await UpdateDatabaseSettings(settings.ThroughputDatabaseName, cancellationToken);

await IndexDeployment.CreateIndexesAsync(typeof(DatabaseSetup).Assembly, documentStore, cancellationToken);

await StartupChecks.WarnIfIndexesUseCorax(documentStore, settings.DatabaseName, cancellationToken);
Expand All @@ -41,7 +37,8 @@ async Task CreateDatabase(string databaseName, CancellationToken cancellationTok
var databaseRecord = new DatabaseRecord(databaseName);

// New databases use Lucene: smaller indexes, lower memory usage and faster for our index definitions.
// Existing databases keep the engine they were created with, see UpdateDatabaseSettings.
// The settings of an existing database are left to the operator. An index keeps the engine it was
// built with until it is rebuilt, so the database default does not change existing indexes.
databaseRecord.Settings.Add("Indexing.Auto.SearchEngineType", "Lucene");
databaseRecord.Settings.Add("Indexing.Static.SearchEngineType", "Lucene");

Expand All @@ -54,31 +51,6 @@ async Task CreateDatabase(string databaseName, CancellationToken cancellationTok
}
}

async Task UpdateDatabaseSettings(string databaseName, CancellationToken cancellationToken)
{
var dbRecord = await documentStore.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(databaseName), cancellationToken);

if (dbRecord is null)
{
throw new InvalidOperationException($"Database '{databaseName}' does not exist.");
}

// Existing databases keep their configured search engine. Changing it would trigger a full rebuild of all
// indexes, which can take a long time and a lot of resources on large databases. Databases created before the
// search engine was pinned explicitly get Corax, which was the default at the time.
var updated = false;

updated |= dbRecord.Settings.TryAdd("Indexing.Auto.SearchEngineType", "Corax");
updated |= dbRecord.Settings.TryAdd("Indexing.Static.SearchEngineType", "Corax");

if (updated)
{
await documentStore.Maintenance.ForDatabase(databaseName).SendAsync(new PutDatabaseSettingsOperation(databaseName, dbRecord.Settings), cancellationToken);
await documentStore.Maintenance.Server.SendAsync(new ToggleDatabasesStateOperation(databaseName, true), cancellationToken);
await documentStore.Maintenance.Server.SendAsync(new ToggleDatabasesStateOperation(databaseName, false), cancellationToken);
}
}

async Task ConfigureExpiration(RavenPersisterSettings settings, CancellationToken cancellationToken)
{
var expirationConfig = new ExpirationConfiguration
Expand Down
Loading