From ae7596717c4b801ed3f97f9040e0dc72803be2e5 Mon Sep 17 00:00:00 2001 From: John Simons Date: Wed, 12 Aug 2026 07:14:09 +1000 Subject: [PATCH] Propagate cancellation tokens through failed message editing and notification persistence This change continues the effort to consistently apply optional `CancellationToken` parameters to asynchronous methods within the `IEditFailedMessagesDataStore`, `INotificationsDataStore`, and related manager interfaces, along with their EFCore and RavenDB implementations. Cancellation tokens are now propagated to underlying asynchronous database calls, ensuring proper cancellation of long-running operations. --- .../When_email_notifications_are_enabled.cs | 10 +++++----- .../EditFailedMessagesDataStore.cs | 2 +- .../EditFailedMessagesManager.cs | 16 +++++++-------- .../Implementation/NotificationsDataStore.cs | 2 +- .../Implementation/NotificationsManager.cs | 8 ++++---- .../Editing/EditFailedMessageManager.cs | 15 +++++++------- .../Editing/EditFailedMessagesDataStore.cs | 5 +++-- .../Editing/NotificationsDataStore.cs | 5 +++-- .../Editing/NotificationsManager.cs | 7 ++++--- .../RavenTransactionalDataStore.cs | 3 ++- .../IDataSessionManager.cs | 3 ++- .../IEditFailedMessagesDataStore.cs | 3 ++- .../IEditFailedMessagesManager.cs | 9 +++++---- .../INotificationsDataStore.cs | 3 ++- .../INotificationsManager.cs | 3 ++- .../EditFailedMessagesControllerAuditTests.cs | 12 +++++------ .../Api/EditFailedMessagesController.cs | 4 ++-- .../Api/NotificationsController.cs | 20 +++++++++---------- .../Email/SendEmailNotificationHandler.cs | 4 ++-- .../Recoverability/Editing/EditHandler.cs | 12 +++++------ 20 files changed, 78 insertions(+), 68 deletions(-) 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 e797fe8edd..2a40ce30b4 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 @@ -62,18 +62,18 @@ await Define(c => class SetupNotificationSettings(INotificationsDataStore notificationsDataStore) : IHostedService { - public async Task StartAsync(CancellationToken cancellationToken) + public async Task StartAsync(CancellationToken cancellationToken = default) { - await using var notificationsManager = await notificationsDataStore.CreateNotificationsManager(); + await using var notificationsManager = await notificationsDataStore.CreateNotificationsManager(cancellationToken); - var settings = await notificationsManager.LoadSettings(); + var settings = await notificationsManager.LoadSettings(cancellationToken); settings.Email.Enabled = true; settings.Email.From = "YouServiceControl@particular.net"; settings.Email.To = "WhoeverMightBeConcerned@particular.net"; - await notificationsManager.SaveChanges(); + await notificationsManager.SaveChanges(cancellationToken); } - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + public Task StopAsync(CancellationToken cancellationToken = default) => Task.CompletedTask; } public class MyContext : ScenarioContext diff --git a/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesDataStore.cs b/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesDataStore.cs index 059f6ed5fb..d902b300e1 100644 --- a/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesDataStore.cs +++ b/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesDataStore.cs @@ -5,7 +5,7 @@ namespace ServiceControl.Persistence.EFCore.Implementation; public class EditFailedMessagesDataStore(IServiceScopeFactory scopeFactory, TimeProvider timeProvider) : IEditFailedMessagesDataStore { - public Task CreateEditFailedMessageManager() + public Task CreateEditFailedMessageManager(CancellationToken cancellationToken = default) { var scope = scopeFactory.CreateAsyncScope(); return Task.FromResult( diff --git a/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesManager.cs b/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesManager.cs index 7e066b84fb..fb1eafc8e3 100644 --- a/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesManager.cs +++ b/src/ServiceControl.Persistence.EFCore/Implementation/EditFailedMessagesManager.cs @@ -10,7 +10,7 @@ public class EditFailedMessagesManager(IAsyncDisposable scope, ServiceControlDbC FailedMessage? failedMessage; // cached after GetFailedMessage FailedMessageEditEntity? editEntity; // tracked after GetCurrentEditingRequestId / SetCurrentEditingRequestId - public async Task GetFailedMessage(string failedMessageId) + public async Task GetFailedMessage(string failedMessageId, CancellationToken cancellationToken = default) { if (!Guid.TryParse(failedMessageId, out var uniqueMessageId)) { @@ -19,7 +19,7 @@ public class EditFailedMessagesManager(IAsyncDisposable scope, ServiceControlDbC var entity = await dbContext.FailedMessages .AsNoTracking() - .SingleOrDefaultAsync(message => message.UniqueMessageId == uniqueMessageId); + .SingleOrDefaultAsync(message => message.UniqueMessageId == uniqueMessageId, cancellationToken); if (entity == null) { @@ -34,7 +34,7 @@ public class EditFailedMessagesManager(IAsyncDisposable scope, ServiceControlDbC return result; } - public async Task GetCurrentEditingRequestId(string failedMessageId) + public async Task GetCurrentEditingRequestId(string failedMessageId, CancellationToken cancellationToken = default) { if (!Guid.TryParse(failedMessageId, out var uniqueMessageId)) { @@ -43,12 +43,12 @@ public class EditFailedMessagesManager(IAsyncDisposable scope, ServiceControlDbC editEntity = await dbContext.FailedMessageEdits .AsNoTracking() - .SingleOrDefaultAsync(e => e.UniqueMessageId == uniqueMessageId); + .SingleOrDefaultAsync(e => e.UniqueMessageId == uniqueMessageId, cancellationToken); return editEntity?.EditId; } - public Task SetCurrentEditingRequestId(string editingMessageId) + public Task SetCurrentEditingRequestId(string editingMessageId, CancellationToken cancellationToken = default) { if (failedMessage == null) { @@ -65,7 +65,7 @@ public Task SetCurrentEditingRequestId(string editingMessageId) return Task.CompletedTask; } - public async Task SetFailedMessageAsResolved() + public async Task SetFailedMessageAsResolved(CancellationToken cancellationToken = default) { if (failedMessage == null) { @@ -81,7 +81,7 @@ public async Task SetFailedMessageAsResolved() // swept immediately. var now = timeProvider.GetUtcNow().UtcDateTime; var entity = await dbContext.FailedMessages - .SingleOrDefaultAsync(m => m.UniqueMessageId == Guid.Parse(message.UniqueMessageId)) + .SingleOrDefaultAsync(m => m.UniqueMessageId == Guid.Parse(message.UniqueMessageId), cancellationToken) ?? throw new InvalidOperationException("Failed message entity not found"); entity.Status = FailedMessageStatus.Resolved; @@ -90,7 +90,7 @@ public async Task SetFailedMessageAsResolved() message.Status = FailedMessageStatus.Resolved; } - public Task SaveChanges() => dbContext.SaveChangesAsync(); + public Task SaveChanges(CancellationToken cancellationToken = default) => dbContext.SaveChangesAsync(cancellationToken); public ValueTask DisposeAsync() => scope.DisposeAsync(); } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs index a3c4793539..811dc6433b 100644 --- a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs +++ b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsDataStore.cs @@ -5,7 +5,7 @@ namespace ServiceControl.Persistence.EFCore.Implementation; public class NotificationsDataStore(IServiceProvider serviceProvider) : INotificationsDataStore { - public Task CreateNotificationsManager() + public Task CreateNotificationsManager(CancellationToken cancellationToken = default) { var scope = serviceProvider.CreateAsyncScope(); ServiceControlDbContext serviceControlDbContext = scope.ServiceProvider.GetRequiredService(); diff --git a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs index 760270e5a5..da9ed1ef10 100644 --- a/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs +++ b/src/ServiceControl.Persistence.EFCore/Implementation/NotificationsManager.cs @@ -8,19 +8,19 @@ public class NotificationsManager(IAsyncDisposable scope, ServiceControlDbContex { NotificationsSettings? _settings; - public Task SaveChanges() + public Task SaveChanges(CancellationToken cancellationToken = default) { if (_settings == null) { return Task.CompletedTask; } - return dbContext.StoreSetting(SettingKeys.NotificationEmails, _settings.Email, CancellationToken.None); + return dbContext.StoreSetting(SettingKeys.NotificationEmails, _settings.Email, cancellationToken); } - public async Task LoadSettings() + public async Task LoadSettings(CancellationToken cancellationToken = default) { - var settings = await dbContext.GetSetting(SettingKeys.NotificationEmails, CancellationToken.None); + var settings = await dbContext.GetSetting(SettingKeys.NotificationEmails, cancellationToken); _settings = new NotificationsSettings() { Email = settings ?? new EmailNotifications() }; return _settings; } diff --git a/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessageManager.cs b/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessageManager.cs index eb1c722286..eb6b2587a2 100644 --- a/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessageManager.cs +++ b/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessageManager.cs @@ -1,6 +1,7 @@ namespace ServiceControl.Persistence.RavenDB { using System; + using System.Threading; using System.Threading.Tasks; using Raven.Client.Documents.Session; using ServiceControl.MessageFailures; @@ -19,19 +20,19 @@ public EditFailedMessageManager(IAsyncDocumentSession session, ExpirationManager this.expirationManager = expirationManager; } - public async Task GetFailedMessage(string failedMessageId) + public async Task GetFailedMessage(string failedMessageId, CancellationToken cancellationToken = default) { - failedMessage = await session.LoadAsync(FailedMessageIdGenerator.MakeDocumentId(failedMessageId)); + failedMessage = await session.LoadAsync(FailedMessageIdGenerator.MakeDocumentId(failedMessageId), cancellationToken); return failedMessage; } - public async Task GetCurrentEditingRequestId(string failedMessageId) + public async Task GetCurrentEditingRequestId(string failedMessageId, CancellationToken cancellationToken = default) { - var edit = await session.LoadAsync(FailedMessageEdit.MakeDocumentId(failedMessageId)); + var edit = await session.LoadAsync(FailedMessageEdit.MakeDocumentId(failedMessageId), cancellationToken); return edit?.EditId; } - public Task SetCurrentEditingRequestId(string editingMessageId) + public Task SetCurrentEditingRequestId(string editingMessageId, CancellationToken cancellationToken = default) { if (failedMessage == null) { @@ -42,10 +43,10 @@ public Task SetCurrentEditingRequestId(string editingMessageId) Id = FailedMessageEdit.MakeDocumentId(failedMessage.UniqueMessageId), FailedMessageId = failedMessage.Id, EditId = editingMessageId - }); + }, cancellationToken); } - public Task SetFailedMessageAsResolved() + public Task SetFailedMessageAsResolved(CancellationToken cancellationToken = default) { // Instance is tracked by the document session failedMessage.Status = FailedMessageStatus.Resolved; diff --git a/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessagesDataStore.cs b/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessagesDataStore.cs index 5533487862..87b54cbc18 100644 --- a/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessagesDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/Editing/EditFailedMessagesDataStore.cs @@ -1,11 +1,12 @@ namespace ServiceControl.Persistence.RavenDB.Editing { + using System.Threading; using System.Threading.Tasks; class EditFailedMessagesDataStore(IRavenSessionProvider sessionProvider, ExpirationManager expirationManager) : IEditFailedMessagesDataStore { - public async Task CreateEditFailedMessageManager() => + public async Task CreateEditFailedMessageManager(CancellationToken cancellationToken = default) => // the edit failed message manager manages the lifetime of the session - new EditFailedMessageManager(await sessionProvider.OpenSession(), expirationManager); + new EditFailedMessageManager(await sessionProvider.OpenSession(cancellationToken: cancellationToken), expirationManager); } } diff --git a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs index 9e3c2f2fcc..c5a66c46f4 100644 --- a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsDataStore.cs @@ -1,11 +1,12 @@ namespace ServiceControl.Persistence.RavenDB.Editing { + using System.Threading; using System.Threading.Tasks; class NotificationsDataStore(IRavenSessionProvider sessionProvider) : INotificationsDataStore { - public async Task CreateNotificationsManager() => + public async Task CreateNotificationsManager(CancellationToken cancellationToken = default) => // the notifications manager manages the lifetime of the session - new NotificationsManager(await sessionProvider.OpenSession()); + new NotificationsManager(await sessionProvider.OpenSession(cancellationToken: cancellationToken)); } } diff --git a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs index 6531b6ed7b..f6d67ab8cd 100644 --- a/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs +++ b/src/ServiceControl.Persistence.RavenDB/Editing/NotificationsManager.cs @@ -1,5 +1,6 @@ namespace ServiceControl.Persistence.RavenDB.Editing { + using System.Threading; using System.Threading.Tasks; using Notifications; using Raven.Client.Documents.Session; @@ -8,18 +9,18 @@ class NotificationsManager(IAsyncDocumentSession session) : AbstractSessionManag { const string SingleDocumentId = "NotificationsSettings/All"; - public async Task LoadSettings() + 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); + .LoadAsync(SingleDocumentId, cancellationToken); if (settings == null) { settings = new NotificationsSettingsDocument { Id = SingleDocumentId }; - await Session.StoreAsync(settings); + await Session.StoreAsync(settings, cancellationToken); } return new NotificationsSettings() diff --git a/src/ServiceControl.Persistence.RavenDB/Transactions/RavenTransactionalDataStore.cs b/src/ServiceControl.Persistence.RavenDB/Transactions/RavenTransactionalDataStore.cs index 86138440e8..c7610f5120 100644 --- a/src/ServiceControl.Persistence.RavenDB/Transactions/RavenTransactionalDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/Transactions/RavenTransactionalDataStore.cs @@ -1,5 +1,6 @@ namespace ServiceControl.Persistence.RavenDB { + using System.Threading; using System.Threading.Tasks; using Raven.Client.Documents.Session; @@ -7,7 +8,7 @@ abstract class AbstractSessionManager(IAsyncDocumentSession session) : IDataSess { protected IAsyncDocumentSession Session { get; } = session; - public Task SaveChanges() => Session.SaveChangesAsync(); + public Task SaveChanges(CancellationToken cancellationToken = default) => Session.SaveChangesAsync(cancellationToken); public ValueTask DisposeAsync() { Session.Dispose(); diff --git a/src/ServiceControl.Persistence/IDataSessionManager.cs b/src/ServiceControl.Persistence/IDataSessionManager.cs index b87bd91802..72a91d99b3 100644 --- a/src/ServiceControl.Persistence/IDataSessionManager.cs +++ b/src/ServiceControl.Persistence/IDataSessionManager.cs @@ -1,10 +1,11 @@ namespace ServiceControl.Persistence { using System; + using System.Threading; using System.Threading.Tasks; public interface IDataSessionManager : IAsyncDisposable { - Task SaveChanges(); + Task SaveChanges(CancellationToken cancellationToken = default); } } diff --git a/src/ServiceControl.Persistence/IEditFailedMessagesDataStore.cs b/src/ServiceControl.Persistence/IEditFailedMessagesDataStore.cs index 2892d2bbe3..9c8293d8fb 100644 --- a/src/ServiceControl.Persistence/IEditFailedMessagesDataStore.cs +++ b/src/ServiceControl.Persistence/IEditFailedMessagesDataStore.cs @@ -1,9 +1,10 @@ namespace ServiceControl.Persistence { + using System.Threading; using System.Threading.Tasks; public interface IEditFailedMessagesDataStore { - Task CreateEditFailedMessageManager(); + Task CreateEditFailedMessageManager(CancellationToken cancellationToken = default); } } diff --git a/src/ServiceControl.Persistence/IEditFailedMessagesManager.cs b/src/ServiceControl.Persistence/IEditFailedMessagesManager.cs index 1b1f4146d8..aa99151262 100644 --- a/src/ServiceControl.Persistence/IEditFailedMessagesManager.cs +++ b/src/ServiceControl.Persistence/IEditFailedMessagesManager.cs @@ -1,14 +1,15 @@ #nullable enable namespace ServiceControl.Persistence { + using System.Threading; using System.Threading.Tasks; using ServiceControl.MessageFailures; public interface IEditFailedMessagesManager : IDataSessionManager { - Task GetFailedMessage(string failedMessageId); - Task GetCurrentEditingRequestId(string failedMessageId); - Task SetCurrentEditingRequestId(string editingMessageId); - Task SetFailedMessageAsResolved(); + Task GetFailedMessage(string failedMessageId, CancellationToken cancellationToken = default); + Task GetCurrentEditingRequestId(string failedMessageId, CancellationToken cancellationToken = default); + Task SetCurrentEditingRequestId(string editingMessageId, CancellationToken cancellationToken = default); + Task SetFailedMessageAsResolved(CancellationToken cancellationToken = default); } } diff --git a/src/ServiceControl.Persistence/INotificationsDataStore.cs b/src/ServiceControl.Persistence/INotificationsDataStore.cs index 07beaf472a..d4b4306807 100644 --- a/src/ServiceControl.Persistence/INotificationsDataStore.cs +++ b/src/ServiceControl.Persistence/INotificationsDataStore.cs @@ -1,9 +1,10 @@ namespace ServiceControl.Persistence { + using System.Threading; using System.Threading.Tasks; public interface INotificationsDataStore { - Task CreateNotificationsManager(); + Task CreateNotificationsManager(CancellationToken cancellationToken = default); } } diff --git a/src/ServiceControl.Persistence/INotificationsManager.cs b/src/ServiceControl.Persistence/INotificationsManager.cs index 673932d5ec..ba3a18cec6 100644 --- a/src/ServiceControl.Persistence/INotificationsManager.cs +++ b/src/ServiceControl.Persistence/INotificationsManager.cs @@ -1,10 +1,11 @@ namespace ServiceControl.Persistence { + using System.Threading; using System.Threading.Tasks; using Notifications; public interface INotificationsManager : IDataSessionManager { - Task LoadSettings(); + Task LoadSettings(CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/ServiceControl.UnitTests/MessageFailures/EditFailedMessagesControllerAuditTests.cs b/src/ServiceControl.UnitTests/MessageFailures/EditFailedMessagesControllerAuditTests.cs index df63c51e38..434a1b83c1 100644 --- a/src/ServiceControl.UnitTests/MessageFailures/EditFailedMessagesControllerAuditTests.cs +++ b/src/ServiceControl.UnitTests/MessageFailures/EditFailedMessagesControllerAuditTests.cs @@ -49,11 +49,11 @@ sealed class FakeEditFailedMessagesManager : IEditFailedMessagesManager { public string? CurrentEditingRequestId { get; set; } - public Task SaveChanges() => Task.CompletedTask; - public Task GetFailedMessage(string failedMessageId) => Task.FromResult(null); - public Task GetCurrentEditingRequestId(string failedMessageId) => Task.FromResult(CurrentEditingRequestId); - public Task SetCurrentEditingRequestId(string editingMessageId) => Task.CompletedTask; - public Task SetFailedMessageAsResolved() => Task.CompletedTask; + public Task SaveChanges(CancellationToken cancellationToken = default) => Task.CompletedTask; + public Task GetFailedMessage(string failedMessageId, CancellationToken cancellationToken = default) => Task.FromResult(null); + public Task GetCurrentEditingRequestId(string failedMessageId, CancellationToken cancellationToken = default) => Task.FromResult(CurrentEditingRequestId); + public Task SetCurrentEditingRequestId(string editingMessageId, CancellationToken cancellationToken = default) => Task.CompletedTask; + public Task SetFailedMessageAsResolved(CancellationToken cancellationToken = default) => Task.CompletedTask; public ValueTask DisposeAsync() => ValueTask.CompletedTask; } @@ -63,7 +63,7 @@ sealed class StubErrorMessageDataStore : IFailedMessageQueryDataStore, IEditFail public FailedMessage? ErrorByResult { get; set; } public FakeEditFailedMessagesManager EditManager { get; } = new(); - public Task CreateEditFailedMessageManager() => Task.FromResult(EditManager); + public Task CreateEditFailedMessageManager(CancellationToken cancellationToken = default) => Task.FromResult(EditManager); public Task GetFailedMessage(string failedMessageId, CancellationToken cancellationToken = default) => Task.FromResult(ErrorByResult); public Task GetFailedMessagesByIds(Guid[] ids, CancellationToken cancellationToken = default) => throw new NotImplementedException(); diff --git a/src/ServiceControl/MessageFailures/Api/EditFailedMessagesController.cs b/src/ServiceControl/MessageFailures/Api/EditFailedMessagesController.cs index e1fed0040d..4b8913c345 100644 --- a/src/ServiceControl/MessageFailures/Api/EditFailedMessagesController.cs +++ b/src/ServiceControl/MessageFailures/Api/EditFailedMessagesController.cs @@ -45,8 +45,8 @@ public async Task> Edit(string failedMessageId, } //HINT: This validation is the first one because we want to minimize the chance of two users concurrently execute an edit-retry. - var editManager = await editStore.CreateEditFailedMessageManager(); - var editId = await editManager.GetCurrentEditingRequestId(failedMessageId); + var editManager = await editStore.CreateEditFailedMessageManager(cancellationToken); + var editId = await editManager.GetCurrentEditingRequestId(failedMessageId, cancellationToken); if (editId != null) { logger.LogWarning("Cannot edit message {FailedMessageId} because it has already been edited", failedMessageId); diff --git a/src/ServiceControl/Notifications/Api/NotificationsController.cs b/src/ServiceControl/Notifications/Api/NotificationsController.cs index 2c441a260d..3cf7c750e4 100644 --- a/src/ServiceControl/Notifications/Api/NotificationsController.cs +++ b/src/ServiceControl/Notifications/Api/NotificationsController.cs @@ -20,8 +20,8 @@ public class NotificationsController(INotificationsDataStore store, Settings set [HttpGet] public async Task GetEmailNotificationsSettings(CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(); - var notificationsSettings = await manager.LoadSettings(); + await using var manager = await store.CreateNotificationsManager(cancellationToken); + var notificationsSettings = await manager.LoadSettings(cancellationToken); return notificationsSettings.Email; } @@ -31,12 +31,12 @@ public async Task GetEmailNotificationsSettings(Cancellation [HttpPost] public async Task ToggleEmailNotifications(ToggleEmailNotifications request, CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(); - var notificationsSettings = await manager.LoadSettings(); + await using var manager = await store.CreateNotificationsManager(cancellationToken); + var notificationsSettings = await manager.LoadSettings(cancellationToken); notificationsSettings.Email.Enabled = request.Enabled; - await manager.SaveChanges(); + await manager.SaveChanges(cancellationToken); return Ok(); } @@ -46,8 +46,8 @@ public async Task ToggleEmailNotifications(ToggleEmailNotificatio [HttpPost] public async Task UpdateSettings(UpdateEmailNotificationsSettingsRequest request, CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(); - var notificationsSettings = await manager.LoadSettings(); + await using var manager = await store.CreateNotificationsManager(cancellationToken); + var notificationsSettings = await manager.LoadSettings(cancellationToken); var emailSettings = notificationsSettings.Email; @@ -61,7 +61,7 @@ public async Task UpdateSettings(UpdateEmailNotificationsSettings emailSettings.From = request.From; emailSettings.To = request.To; - await manager.SaveChanges(); + await manager.SaveChanges(cancellationToken); return Ok(); } @@ -71,8 +71,8 @@ public async Task UpdateSettings(UpdateEmailNotificationsSettings [HttpPost] public async Task SendTestEmail(CancellationToken cancellationToken = default) { - await using var manager = await store.CreateNotificationsManager(); - var notificationsSettings = await manager.LoadSettings(); + await using var manager = await store.CreateNotificationsManager(cancellationToken); + var notificationsSettings = await manager.LoadSettings(cancellationToken); try { diff --git a/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs b/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs index 1ff11a1b15..c321bff473 100644 --- a/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs +++ b/src/ServiceControl/Notifications/Email/SendEmailNotificationHandler.cs @@ -17,9 +17,9 @@ public async Task Handle(SendEmailNotification message, IMessageHandlerContext c { NotificationsSettings notifications; - await using (var manager = await store.CreateNotificationsManager()) + await using (var manager = await store.CreateNotificationsManager(context.CancellationToken)) { - notifications = await manager.LoadSettings(); + notifications = await manager.LoadSettings(context.CancellationToken); } logger.LogInformation("Processing email notification. Subject: {Subject}, Body: {Body}", message.Subject, message.Body); diff --git a/src/ServiceControl/Recoverability/Editing/EditHandler.cs b/src/ServiceControl/Recoverability/Editing/EditHandler.cs index 69104dce30..9b7f68dc0b 100644 --- a/src/ServiceControl/Recoverability/Editing/EditHandler.cs +++ b/src/ServiceControl/Recoverability/Editing/EditHandler.cs @@ -24,9 +24,9 @@ public async Task Handle(EditAndSend message, IMessageHandlerContext context) { FailedMessage failedMessage; string editId; - await using (var session = await store.CreateEditFailedMessageManager()) + await using (var session = await store.CreateEditFailedMessageManager(context.CancellationToken)) { - failedMessage = await session.GetFailedMessage(message.FailedMessageId); + failedMessage = await session.GetFailedMessage(message.FailedMessageId, context.CancellationToken); if (failedMessage == null) { @@ -34,7 +34,7 @@ public async Task Handle(EditAndSend message, IMessageHandlerContext context) return; } - editId = await session.GetCurrentEditingRequestId(message.FailedMessageId); + editId = await session.GetCurrentEditingRequestId(message.FailedMessageId, context.CancellationToken); if (editId == null) { if (failedMessage.Status != FailedMessageStatus.Unresolved) @@ -44,7 +44,7 @@ public async Task Handle(EditAndSend message, IMessageHandlerContext context) } // create a retries document to prevent concurrent edits - await session.SetCurrentEditingRequestId(context.MessageId); + await session.SetCurrentEditingRequestId(context.MessageId, context.CancellationToken); } else if (editId != context.MessageId) { @@ -53,10 +53,10 @@ public async Task Handle(EditAndSend message, IMessageHandlerContext context) } // the original failure is marked as resolved as any failures of the edited message are treated as a new message failure. - await session.SetFailedMessageAsResolved(); + await session.SetFailedMessageAsResolved(context.CancellationToken); - await session.SaveChanges(); + await session.SaveChanges(context.CancellationToken); } var redirects = await redirectsStore.GetRedirects(context.CancellationToken);