diff --git a/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_email_notifications_are_enabled.cs b/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_email_notifications_are_enabled.cs index 2a40ce30b4..90aa621448 100644 --- a/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_email_notifications_are_enabled.cs +++ b/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_email_notifications_are_enabled.cs @@ -64,13 +64,11 @@ class SetupNotificationSettings(INotificationsDataStore notificationsDataStore) { public async Task StartAsync(CancellationToken cancellationToken = default) { - await using var notificationsManager = await notificationsDataStore.CreateNotificationsManager(cancellationToken); - - var settings = await notificationsManager.LoadSettings(cancellationToken); + var settings = await notificationsDataStore.LoadSettings(cancellationToken); settings.Email.Enabled = true; settings.Email.From = "YouServiceControl@particular.net"; settings.Email.To = "WhoeverMightBeConcerned@particular.net"; - await notificationsManager.SaveChanges(cancellationToken); + await notificationsDataStore.SaveSettings(settings, cancellationToken); } public Task StopAsync(CancellationToken cancellationToken = default) => Task.CompletedTask; diff --git a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs index 811dc6433b..ecad3d405d 100644 --- a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs +++ b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs @@ -1,14 +1,18 @@ namespace ServiceControl.Persistence.EFCore.Implementation; -using DbContexts; +using Infrastructure; using Microsoft.Extensions.DependencyInjection; +using Notifications; -public class NotificationsDataStore(IServiceProvider serviceProvider) : INotificationsDataStore +public class NotificationsDataStore(IServiceScopeFactory scopeFactory) : DataStoreBase(scopeFactory), INotificationsDataStore { - public Task CreateNotificationsManager(CancellationToken cancellationToken = default) - { - var scope = serviceProvider.CreateAsyncScope(); - ServiceControlDbContext serviceControlDbContext = scope.ServiceProvider.GetRequiredService(); - return Task.FromResult(new NotificationsManager(scope, serviceControlDbContext)); - } -} + public Task LoadSettings(CancellationToken cancellationToken = default) => + ExecuteWithDbContext(async (dbContext, ct) => + { + var email = await dbContext.GetSetting(SettingKeys.NotificationEmails, ct); + return new NotificationsSettings { Email = email ?? new EmailNotifications() }; + }, cancellationToken); + + public Task SaveSettings(NotificationsSettings settings, CancellationToken cancellationToken = default) => + ExecuteWithDbContext((dbContext, ct) => dbContext.StoreSetting(SettingKeys.NotificationEmails, settings.Email, ct), cancellationToken); +} \ No newline at end of file diff --git a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs deleted file mode 100644 index da9ed1ef10..0000000000 --- a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace ServiceControl.Persistence.EFCore.Implementation; - -using DbContexts; -using Infrastructure; -using Notifications; - -public class NotificationsManager(IAsyncDisposable scope, ServiceControlDbContext dbContext) : INotificationsManager -{ - NotificationsSettings? _settings; - - public Task SaveChanges(CancellationToken cancellationToken = default) - { - if (_settings == null) - { - return Task.CompletedTask; - } - - return dbContext.StoreSetting(SettingKeys.NotificationEmails, _settings.Email, cancellationToken); - } - - public async Task LoadSettings(CancellationToken cancellationToken = default) - { - var settings = await dbContext.GetSetting(SettingKeys.NotificationEmails, cancellationToken); - _settings = new NotificationsSettings() { Email = settings ?? new EmailNotifications() }; - return _settings; - } - - public async ValueTask DisposeAsync() - { - await dbContext.DisposeAsync(); - await scope.DisposeAsync(); - - GC.SuppressFinalize(this); - } -} \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs index c5a66c46f4..f374c980a8 100644 --- a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs @@ -2,11 +2,46 @@ namespace ServiceControl.Persistence.RavenDB.Editing { using System.Threading; using System.Threading.Tasks; + using Notifications; class NotificationsDataStore(IRavenSessionProvider sessionProvider) : INotificationsDataStore { - public async Task CreateNotificationsManager(CancellationToken cancellationToken = default) => - // the notifications manager manages the lifetime of the session - new NotificationsManager(await sessionProvider.OpenSession(cancellationToken: cancellationToken)); + const string SingleDocumentId = "NotificationsSettings/All"; + + public async Task LoadSettings(CancellationToken cancellationToken = default) + { + using var session = await sessionProvider.OpenSession(cancellationToken: cancellationToken); + var document = await session.LoadAsync(SingleDocumentId, cancellationToken); + + return new NotificationsSettings + { + Email = Copy(document?.Email ?? new EmailNotifications()) + }; + } + + public async Task SaveSettings(NotificationsSettings settings, CancellationToken cancellationToken = default) + { + using var session = await sessionProvider.OpenSession(cancellationToken: cancellationToken); + var document = new NotificationsSettingsDocument + { + Id = SingleDocumentId, + Email = Copy(settings.Email) + }; + + await session.StoreAsync(document, SingleDocumentId, cancellationToken); + await session.SaveChangesAsync(cancellationToken); + } + + static EmailNotifications Copy(EmailNotifications source) => new() + { + Enabled = source.Enabled, + SmtpServer = source.SmtpServer, + SmtpPort = source.SmtpPort, + AuthenticationAccount = source.AuthenticationAccount, + AuthenticationPassword = source.AuthenticationPassword, + EnableTLS = source.EnableTLS, + To = source.To, + From = source.From + }; } } diff --git a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs deleted file mode 100644 index f6d67ab8cd..0000000000 --- a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace ServiceControl.Persistence.RavenDB.Editing -{ - using System.Threading; - using System.Threading.Tasks; - using Notifications; - using Raven.Client.Documents.Session; - - class NotificationsManager(IAsyncDocumentSession session) : AbstractSessionManager(session), INotificationsManager - { - const string SingleDocumentId = "NotificationsSettings/All"; - - public async Task LoadSettings(CancellationToken cancellationToken = default) - { - // Deliberately not aggressively cached. These settings are read rarely and edited by hand, - // and aggressive caching invalidates asynchronously via the Changes API, so a read straight - // after a save can return the pre-save document. - var settings = await Session - .LoadAsync(SingleDocumentId, cancellationToken); - - if (settings == null) - { - settings = new NotificationsSettingsDocument { Id = SingleDocumentId }; - await Session.StoreAsync(settings, cancellationToken); - } - - return new NotificationsSettings() - { - Email = settings.Email - }; - } - } -} \ No newline at end of file diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/PersistenceTestsContext.cs b/src/ServiceControl.Persistence.Tests.RavenDB/PersistenceTestsContext.cs index bf77772c9e..342dbc8bce 100644 --- a/src/ServiceControl.Persistence.Tests.RavenDB/PersistenceTestsContext.cs +++ b/src/ServiceControl.Persistence.Tests.RavenDB/PersistenceTestsContext.cs @@ -3,11 +3,13 @@ namespace ServiceControl.Persistence.Tests; using System; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using NUnit.Framework; using Raven.Client.Documents; +using Raven.Client.Documents.Session; using ServiceControl.Contracts.Operations; using ServiceControl.MessageFailures; using ServiceControl.Persistence; diff --git a/src/ServiceControl.Persistence.Tests/EFCore/PersistenceTestsContext.cs b/src/ServiceControl.Persistence.Tests/EFCore/PersistenceTestsContext.cs index 5744d6ec3b..0424b0071b 100644 --- a/src/ServiceControl.Persistence.Tests/EFCore/PersistenceTestsContext.cs +++ b/src/ServiceControl.Persistence.Tests/EFCore/PersistenceTestsContext.cs @@ -5,11 +5,13 @@ namespace ServiceControl.Persistence.Tests; using System.Collections.Generic; using System.Linq; using System.Text.Json; +using System.Threading; using System.Threading.Tasks; using EFCore.DbContexts; using EFCore.Entities; using EFCore.Infrastructure; using MessageFailures; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Time.Testing; using NServiceBus; diff --git a/src/ServiceControl.Persistence.Tests/IPersistenceTestsContext.cs b/src/ServiceControl.Persistence.Tests/IPersistenceTestsContext.cs index abf74b0b33..4128de9df9 100644 --- a/src/ServiceControl.Persistence.Tests/IPersistenceTestsContext.cs +++ b/src/ServiceControl.Persistence.Tests/IPersistenceTestsContext.cs @@ -1,3 +1,4 @@ +#nullable enable namespace ServiceControl.Persistence.Tests; using System.Threading.Tasks; @@ -18,4 +19,4 @@ public interface IPersistenceTestsContext string GenerateFailedMessageRecordId(string messageId); Task InsertFailedMessages(params FailedMessage[] messages); -} \ No newline at end of file +} diff --git a/src/ServiceControl.Persistence.Tests/NotificationsDataStoreTests.cs b/src/ServiceControl.Persistence.Tests/NotificationsDataStoreTests.cs index 0c31cdc66e..c852481027 100644 --- a/src/ServiceControl.Persistence.Tests/NotificationsDataStoreTests.cs +++ b/src/ServiceControl.Persistence.Tests/NotificationsDataStoreTests.cs @@ -1,16 +1,17 @@ namespace ServiceControl.Persistence.Tests; +using System; +using System.Threading; using System.Threading.Tasks; using NUnit.Framework; +using ServiceControl.Notifications; class NotificationsDataStoreTests : PersistenceTestBase { [Test, CancelAfter(30_000)] public async Task LoadSettings_returns_defaults_when_no_settings_exist() { - await using var manager = await NotificationsStore.CreateNotificationsManager(); - - var settings = await manager.LoadSettings(); + var settings = await NotificationsStore.LoadSettings(TestContext.CurrentContext.CancellationToken); using (Assert.EnterMultipleScope()) { @@ -28,140 +29,109 @@ public async Task LoadSettings_returns_defaults_when_no_settings_exist() } [Test, CancelAfter(30_000)] - public async Task SaveChanges_persists_email_settings_round_trip() + public void LoadSettings_propagates_cancellation() { - await using (var manager = await NotificationsStore.CreateNotificationsManager()) - { - var settings = await manager.LoadSettings(); - - settings.Email.Enabled = true; - settings.Email.SmtpServer = "smtp.example.com"; - settings.Email.SmtpPort = 587; - settings.Email.EnableTLS = true; - settings.Email.From = "sc@example.com"; - settings.Email.To = "ops@example.com"; - settings.Email.AuthenticationAccount = "user"; - settings.Email.AuthenticationPassword = "p@ssw0rd"; - - await manager.SaveChanges(); - } - - await CompleteDatabaseOperation(); + using var cancellation = new CancellationTokenSource(); + cancellation.Cancel(); - await using var verifyManager = await NotificationsStore.CreateNotificationsManager(); - var loaded = await verifyManager.LoadSettings(); - - using (Assert.EnterMultipleScope()) - { - Assert.That(loaded.Email.Enabled, Is.True); - Assert.That(loaded.Email.SmtpServer, Is.EqualTo("smtp.example.com")); - Assert.That(loaded.Email.SmtpPort, Is.EqualTo(587)); - Assert.That(loaded.Email.EnableTLS, Is.True); - Assert.That(loaded.Email.From, Is.EqualTo("sc@example.com")); - Assert.That(loaded.Email.To, Is.EqualTo("ops@example.com")); - Assert.That(loaded.Email.AuthenticationAccount, Is.EqualTo("user")); - Assert.That(loaded.Email.AuthenticationPassword, Is.EqualTo("p@ssw0rd")); - } + Assert.That( + async () => await NotificationsStore.LoadSettings(cancellation.Token), + Throws.InstanceOf()); } [Test, CancelAfter(30_000)] - public async Task Toggling_enabled_is_persisted() + public void SaveSettings_propagates_cancellation() { - await using (var manager = await NotificationsStore.CreateNotificationsManager()) - { - var settings = await manager.LoadSettings(); - settings.Email.Enabled = true; - await manager.SaveChanges(); - } + using var cancellation = new CancellationTokenSource(); + cancellation.Cancel(); - await CompleteDatabaseOperation(); - - await using (var manager = await NotificationsStore.CreateNotificationsManager()) - { - var settings = await manager.LoadSettings(); - Assert.That(settings.Email.Enabled, Is.True); + Assert.That( + async () => await NotificationsStore.SaveSettings(CreateSettings("cancelled.smtp"), cancellation.Token), + Throws.InstanceOf()); + } - settings.Email.Enabled = false; - await manager.SaveChanges(); - } + [Test, CancelAfter(30_000)] + public async Task SaveSettings_without_a_prior_load_round_trips_all_values() + { + var settings = CreateSettings("smtp.example.com"); + await NotificationsStore.SaveSettings(settings, TestContext.CurrentContext.CancellationToken); await CompleteDatabaseOperation(); - await using var verifyManager = await NotificationsStore.CreateNotificationsManager(); - var final = await verifyManager.LoadSettings(); - Assert.That(final.Email.Enabled, Is.False); + var loaded = await NotificationsStore.LoadSettings(TestContext.CurrentContext.CancellationToken); + AssertSettings(loaded, "smtp.example.com"); } [Test, CancelAfter(30_000)] - public async Task LoadSettings_returns_previously_saved_settings() + public async Task SaveSettings_replaces_the_persisted_snapshot() { - await using (var manager = await NotificationsStore.CreateNotificationsManager()) - { - var settings = await manager.LoadSettings(); - settings.Email.SmtpServer = "configured.server"; - settings.Email.SmtpPort = 2525; - await manager.SaveChanges(); - } + await NotificationsStore.SaveSettings(CreateSettings("original.smtp"), TestContext.CurrentContext.CancellationToken); - await CompleteDatabaseOperation(); + var replacement = CreateSettings("replacement.smtp"); + replacement.Email.Enabled = false; + replacement.Email.SmtpPort = 2525; + replacement.Email.To = "replacement@example.com"; + await NotificationsStore.SaveSettings(replacement, TestContext.CurrentContext.CancellationToken); + + replacement.Email.SmtpServer = "mutated.after.save"; + replacement.Email.To = "mutated@example.com"; - await using var manager2 = await NotificationsStore.CreateNotificationsManager(); - var loaded = await manager2.LoadSettings(); + await CompleteDatabaseOperation(); + var loaded = await NotificationsStore.LoadSettings(TestContext.CurrentContext.CancellationToken); using (Assert.EnterMultipleScope()) { - Assert.That(loaded.Email.SmtpServer, Is.EqualTo("configured.server")); - Assert.That(loaded.Email.SmtpPort, Is.EqualTo(2525)); - // Untouched fields keep their defaults + Assert.That(loaded, Is.Not.SameAs(replacement)); + Assert.That(loaded.Email, Is.Not.SameAs(replacement.Email)); Assert.That(loaded.Email.Enabled, Is.False); - Assert.That(loaded.Email.EnableTLS, Is.False); + Assert.That(loaded.Email.SmtpServer, Is.EqualTo("replacement.smtp")); + Assert.That(loaded.Email.SmtpPort, Is.EqualTo(2525)); + Assert.That(loaded.Email.To, Is.EqualTo("replacement@example.com")); + Assert.That(loaded.Email.From, Is.EqualTo("sc@example.com")); } } [Test, CancelAfter(30_000)] - public async Task Updating_individual_fields_preserves_others() + public async Task Repeated_saves_behave_consistently() { - await using (var manager = await NotificationsStore.CreateNotificationsManager()) - { - var settings = await manager.LoadSettings(); - settings.Email.Enabled = true; - settings.Email.SmtpServer = "original.smtp"; - settings.Email.SmtpPort = 25; - settings.Email.EnableTLS = false; - settings.Email.From = "from@orig"; - settings.Email.To = "to@orig"; - settings.Email.AuthenticationAccount = "acct"; - settings.Email.AuthenticationPassword = "secret"; - await manager.SaveChanges(); - } + var settings = CreateSettings("repeat.smtp"); + + await NotificationsStore.SaveSettings(settings, TestContext.CurrentContext.CancellationToken); + await NotificationsStore.SaveSettings(settings, TestContext.CurrentContext.CancellationToken); + await NotificationsStore.SaveSettings(settings, TestContext.CurrentContext.CancellationToken); await CompleteDatabaseOperation(); + var loaded = await NotificationsStore.LoadSettings(TestContext.CurrentContext.CancellationToken); + AssertSettings(loaded, "repeat.smtp"); + } - await using (var manager = await NotificationsStore.CreateNotificationsManager()) + static NotificationsSettings CreateSettings(string smtpServer) => new() + { + Email = new EmailNotifications { - var settings = await manager.LoadSettings(); - settings.Email.SmtpServer = "updated.smtp"; - settings.Email.EnableTLS = true; - await manager.SaveChanges(); + Enabled = true, + SmtpServer = smtpServer, + SmtpPort = 587, + EnableTLS = true, + From = "sc@example.com", + To = "ops@example.com", + AuthenticationAccount = "user", + AuthenticationPassword = "p@ssw0rd" } + }; - await CompleteDatabaseOperation(); - - await using var verifyManager = await NotificationsStore.CreateNotificationsManager(); - var loaded = await verifyManager.LoadSettings(); - + static void AssertSettings(NotificationsSettings settings, string smtpServer) + { using (Assert.EnterMultipleScope()) { - // Updated fields - Assert.That(loaded.Email.SmtpServer, Is.EqualTo("updated.smtp")); - Assert.That(loaded.Email.EnableTLS, Is.True); - // Preserved fields - Assert.That(loaded.Email.Enabled, Is.True); - Assert.That(loaded.Email.SmtpPort, Is.EqualTo(25)); - Assert.That(loaded.Email.From, Is.EqualTo("from@orig")); - Assert.That(loaded.Email.To, Is.EqualTo("to@orig")); - Assert.That(loaded.Email.AuthenticationAccount, Is.EqualTo("acct")); - Assert.That(loaded.Email.AuthenticationPassword, Is.EqualTo("secret")); + Assert.That(settings.Email.Enabled, Is.True); + Assert.That(settings.Email.SmtpServer, Is.EqualTo(smtpServer)); + Assert.That(settings.Email.SmtpPort, Is.EqualTo(587)); + Assert.That(settings.Email.EnableTLS, Is.True); + Assert.That(settings.Email.From, Is.EqualTo("sc@example.com")); + Assert.That(settings.Email.To, Is.EqualTo("ops@example.com")); + Assert.That(settings.Email.AuthenticationAccount, Is.EqualTo("user")); + Assert.That(settings.Email.AuthenticationPassword, Is.EqualTo("p@ssw0rd")); } } -} \ No newline at end of file +} diff --git a/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs b/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs index bee2026528..0e684356a8 100644 --- a/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs +++ b/src/ServiceControl.Persistence.Tests/PersistenceTestBase.cs @@ -1,6 +1,7 @@ namespace ServiceControl.Persistence.Tests; using System; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -12,6 +13,7 @@ using ServiceControl.Infrastructure; using ServiceControl.Infrastructure.Auth; using ServiceControl.Infrastructure.DomainEvents; +using ServiceControl.MessageFailures; using ServiceControl.Operations.BodyStorage; using ServiceControl.Persistence; using ServiceControl.Persistence.MessageRedirects; diff --git a/src/ServiceControl.Persistence/INotificationsDataStore.cs b/src/ServiceControl.Persistence/INotificationsDataStore.cs index d4b4306807..bc55c196ed 100644 --- a/src/ServiceControl.Persistence/INotificationsDataStore.cs +++ b/src/ServiceControl.Persistence/INotificationsDataStore.cs @@ -2,9 +2,26 @@ namespace ServiceControl.Persistence { using System.Threading; using System.Threading.Tasks; + using Notifications; + /// + /// Loads and saves notification settings as detached snapshots. + /// public interface INotificationsDataStore { - Task CreateNotificationsManager(CancellationToken cancellationToken = default); + /// + /// Loads the persisted notification settings, or returns default settings when none have been saved. + /// + /// Token used to cancel the operation. + /// A mutable snapshot that is not tracked by the persistence provider. + Task LoadSettings(CancellationToken cancellationToken = default); + + /// + /// Replaces the persisted notification settings with the supplied snapshot. + /// + /// The complete settings snapshot to persist. + /// Token used to cancel the operation. + /// A task that completes after the snapshot has been persisted. + Task SaveSettings(NotificationsSettings settings, CancellationToken cancellationToken = default); } } diff --git a/src/ServiceControl.Persistence/INotificationsManager.cs b/src/ServiceControl.Persistence/INotificationsManager.cs deleted file mode 100644 index ba3a18cec6..0000000000 --- a/src/ServiceControl.Persistence/INotificationsManager.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ServiceControl.Persistence -{ - using System.Threading; - using System.Threading.Tasks; - using Notifications; - - public interface INotificationsManager : IDataSessionManager - { - Task LoadSettings(CancellationToken cancellationToken = default); - } -} \ No newline at end of file diff --git a/src/ServiceControl/Notifications/Api/NotificationsController.cs b/src/ServiceControl/Notifications/Api/NotificationsController.cs index 3cf7c750e4..91ea380b2f 100644 --- a/src/ServiceControl/Notifications/Api/NotificationsController.cs +++ b/src/ServiceControl/Notifications/Api/NotificationsController.cs @@ -20,8 +20,7 @@ public class NotificationsController(INotificationsDataStore store, Settings set [HttpGet] public async Task GetEmailNotificationsSettings(CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(cancellationToken); - var notificationsSettings = await manager.LoadSettings(cancellationToken); + var notificationsSettings = await store.LoadSettings(cancellationToken); return notificationsSettings.Email; } @@ -31,12 +30,11 @@ public async Task GetEmailNotificationsSettings(Cancellation [HttpPost] public async Task ToggleEmailNotifications(ToggleEmailNotifications request, CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(cancellationToken); - var notificationsSettings = await manager.LoadSettings(cancellationToken); + var notificationsSettings = await store.LoadSettings(cancellationToken); notificationsSettings.Email.Enabled = request.Enabled; - await manager.SaveChanges(cancellationToken); + await store.SaveSettings(notificationsSettings, cancellationToken); return Ok(); } @@ -46,8 +44,7 @@ public async Task ToggleEmailNotifications(ToggleEmailNotificatio [HttpPost] public async Task UpdateSettings(UpdateEmailNotificationsSettingsRequest request, CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(cancellationToken); - var notificationsSettings = await manager.LoadSettings(cancellationToken); + var notificationsSettings = await store.LoadSettings(cancellationToken); var emailSettings = notificationsSettings.Email; @@ -61,7 +58,7 @@ public async Task UpdateSettings(UpdateEmailNotificationsSettings emailSettings.From = request.From; emailSettings.To = request.To; - await manager.SaveChanges(cancellationToken); + await store.SaveSettings(notificationsSettings, cancellationToken); return Ok(); } @@ -71,8 +68,7 @@ public async Task UpdateSettings(UpdateEmailNotificationsSettings [HttpPost] public async Task SendTestEmail(CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(cancellationToken); - var notificationsSettings = await manager.LoadSettings(cancellationToken); + var notificationsSettings = await store.LoadSettings(cancellationToken); try { diff --git a/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs b/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs index c321bff473..53b70fa78a 100644 --- a/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs +++ b/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs @@ -15,12 +15,7 @@ class SendEmailNotificationHandler(INotificationsDataStore store, Settings setti { public async Task Handle(SendEmailNotification message, IMessageHandlerContext context) { - NotificationsSettings notifications; - - await using (var manager = await store.CreateNotificationsManager(context.CancellationToken)) - { - notifications = await manager.LoadSettings(context.CancellationToken); - } + var notifications = await store.LoadSettings(context.CancellationToken); logger.LogInformation("Processing email notification. Subject: {Subject}, Body: {Body}", message.Subject, message.Body);