diff --git a/src/Particular.LicensingComponent/.editorconfig b/src/Particular.LicensingComponent/.editorconfig index 97adb8c6b7..423278de8e 100644 --- a/src/Particular.LicensingComponent/.editorconfig +++ b/src/Particular.LicensingComponent/.editorconfig @@ -12,11 +12,3 @@ dotnet_diagnostic.IDE0010.severity = suggestion csharp_style_var_elsewhere = true:error csharp_style_var_for_built_in_types = true:error - -# Cancellation analyzer debt. These fire because Particular.Analyzers is no longer pinned to 0.9.0. -# They are scheduled work, not accepted exceptions: remove a line once this project has no -# violations of that rule left, and never add a rule back to this list. -dotnet_diagnostic.PS0003.severity = none -dotnet_diagnostic.PS0008.severity = none -dotnet_diagnostic.PS0017.severity = none -dotnet_diagnostic.PS0019.severity = none diff --git a/src/Particular.LicensingComponent/AuditThroughput/AuditQuery.cs b/src/Particular.LicensingComponent/AuditThroughput/AuditQuery.cs index 7227159665..619a6ebae6 100644 --- a/src/Particular.LicensingComponent/AuditThroughput/AuditQuery.cs +++ b/src/Particular.LicensingComponent/AuditThroughput/AuditQuery.cs @@ -17,7 +17,7 @@ public class AuditQuery(ILogger logger, IEndpointsApi endpointsApi, r.SemanticVersion >= MinAuditCountsVersion && r.Retention >= TimeSpan.FromDays(2); - public async Task> GetKnownEndpoints(CancellationToken cancellationToken) + public async Task> GetKnownEndpoints(CancellationToken cancellationToken = default) { var endpoints = await endpointsApi.GetEndpoints(cancellationToken); @@ -36,9 +36,9 @@ public async Task> GetKnownEndpoints(Cancell return scEndpoints ?? []; } - public async Task> GetAuditCountForEndpoint(string endpointUrlName, CancellationToken cancellationToken) => (await auditCountApi.GetEndpointAuditCounts(endpointUrlName, cancellationToken)).Select(s => new AuditCount { Count = s.Count, UtcDate = DateOnly.FromDateTime(s.UtcDate) }); + public async Task> GetAuditCountForEndpoint(string endpointUrlName, CancellationToken cancellationToken = default) => (await auditCountApi.GetEndpointAuditCounts(endpointUrlName, cancellationToken)).Select(s => new AuditCount { Count = s.Count, UtcDate = DateOnly.FromDateTime(s.UtcDate) }); - public async Task> GetAuditRemotes(CancellationToken cancellationToken) + public async Task> GetAuditRemotes(CancellationToken cancellationToken = default) { try { @@ -101,6 +101,10 @@ public async Task> GetAuditRemotes(CancellationT return remotesInfo; } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + throw; + } catch (Exception ex) { logger.LogError(ex, "Failed to get Audit Remotes"); @@ -108,7 +112,7 @@ public async Task> GetAuditRemotes(CancellationT } } - public async Task TestAuditConnection(CancellationToken cancellationToken) + public async Task TestAuditConnection(CancellationToken cancellationToken = default) { var connectionTestResult = new ConnectionSettingsTestResult { ConnectionSuccessful = true }; diff --git a/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs b/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs index 91c90dbb95..8b50f6cece 100644 --- a/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs +++ b/src/Particular.LicensingComponent/AuditThroughput/AuditThroughputCollectorHostedService.cs @@ -18,7 +18,7 @@ public class AuditThroughputCollectorHostedService( public TimeSpan DelayStart { get; set; } = TimeSpan.FromSeconds(40); public static List AuditQueues { get; set; } = []; - protected override async Task ExecuteAsync(CancellationToken cancellationToken) + protected override async Task ExecuteAsync(CancellationToken cancellationToken = default) { logger.LogInformation("Starting {ServiceName}", nameof(AuditThroughputCollectorHostedService)); @@ -34,7 +34,11 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await GatherThroughput(cancellationToken); } - catch (Exception ex) when (ex is not OperationCanceledException) + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + throw; + } + catch (Exception ex) { logger.LogError(ex, "Failed to gather throughput from audit"); } diff --git a/src/Particular.LicensingComponent/AuditThroughput/IAuditQuery.cs b/src/Particular.LicensingComponent/AuditThroughput/IAuditQuery.cs index ea63076356..66f03b7f35 100644 --- a/src/Particular.LicensingComponent/AuditThroughput/IAuditQuery.cs +++ b/src/Particular.LicensingComponent/AuditThroughput/IAuditQuery.cs @@ -8,11 +8,11 @@ public interface IAuditQuery SemanticVersion MinAuditCountsVersion { get; } Func ValidRemoteInstances { get; } - Task> GetKnownEndpoints(CancellationToken cancellationToken); + Task> GetKnownEndpoints(CancellationToken cancellationToken = default); - Task> GetAuditCountForEndpoint(string endpointUrlName, CancellationToken cancellationToken); - Task> GetAuditRemotes(CancellationToken cancellationToken); - Task TestAuditConnection(CancellationToken cancellationToken); + Task> GetAuditCountForEndpoint(string endpointUrlName, CancellationToken cancellationToken = default); + Task> GetAuditRemotes(CancellationToken cancellationToken = default); + Task TestAuditConnection(CancellationToken cancellationToken = default); } } diff --git a/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs b/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs index b8c37d8521..f62b770c1a 100644 --- a/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs +++ b/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs @@ -19,7 +19,7 @@ public class BrokerThroughputCollectorHostedService( { public TimeSpan DelayStart { get; set; } = TimeSpan.FromSeconds(40); - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + protected override async Task ExecuteAsync(CancellationToken cancellationToken = default) { static ReadOnlyDictionary LoadBrokerSettingValues(IEnumerable brokerKeys) => new(brokerKeys.Select(pair => KeyValuePair.Create(pair.Key, SettingsReader.Read(ThroughputSettings.SettingsNamespace, pair.Key))) @@ -37,7 +37,7 @@ static ReadOnlyDictionary LoadBrokerSettingValues(IEnumerable LoadBrokerSettingValues(IEnumerable(); var postfixGenerator = new PostfixGenerator(); - await foreach (var queueName in brokerThroughputQuery.GetQueueNames(stoppingToken)) + await foreach (var queueName in brokerThroughputQuery.GetQueueNames(cancellationToken)) { if (PlatformEndpointHelper.IsPlatformEndpoint(queueName.SanitizedName, throughputSettings)) { @@ -78,13 +82,13 @@ async Task GatherThroughput(CancellationToken stoppingToken) } await Task.WhenAll(waitingTasks); - await dataStore.SaveBrokerMetadata(new BrokerMetadata(brokerThroughputQuery.ScopeType, brokerThroughputQuery.Data), stoppingToken); + await dataStore.SaveBrokerMetadata(new BrokerMetadata(brokerThroughputQuery.ScopeType, brokerThroughputQuery.Data), cancellationToken); return; async Task Exec(IBrokerQueue queueName, string postfix) { var endpointId = new EndpointIdentifier(queueName.QueueName, ThroughputSource.Broker); - var endpoint = await dataStore.GetEndpoint(endpointId, stoppingToken); + var endpoint = await dataStore.GetEndpoint(endpointId, cancellationToken); if (endpoint == null) { @@ -95,14 +99,18 @@ async Task Exec(IBrokerQueue queueName, string postfix) EndpointIndicators = [.. queueName.EndpointIndicators] }; - await dataStore.SaveEndpoint(endpoint, stoppingToken); + await dataStore.SaveEndpoint(endpoint, cancellationToken); } - await foreach (var queueThroughput in brokerThroughputQuery.GetThroughputPerDay(queueName, endpoint.LastCollectedDate.AddDays(1), stoppingToken)) + await foreach (var queueThroughput in brokerThroughputQuery.GetThroughputPerDay(queueName, endpoint.LastCollectedDate.AddDays(1), cancellationToken)) { try { - await dataStore.RecordEndpointThroughput(queueName.QueueName, ThroughputSource.Broker, queueThroughput.DateUTC, queueThroughput.TotalThroughput, stoppingToken); + await dataStore.RecordEndpointThroughput(queueName.QueueName, ThroughputSource.Broker, queueThroughput.DateUTC, queueThroughput.TotalThroughput, cancellationToken); + } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + throw; } catch (Exception e) { diff --git a/src/Particular.LicensingComponent/IThroughputCollector.cs b/src/Particular.LicensingComponent/IThroughputCollector.cs index a880f1c37e..6e325dab79 100644 --- a/src/Particular.LicensingComponent/IThroughputCollector.cs +++ b/src/Particular.LicensingComponent/IThroughputCollector.cs @@ -5,13 +5,13 @@ public interface IThroughputCollector { - Task> GetThroughputSummary(CancellationToken cancellationToken); - Task UpdateUserIndicatorsOnEndpoints(List userIndicatorUpdates, CancellationToken cancellationToken); - Task GetThroughputConnectionSettingsInformation(CancellationToken cancellationToken); - Task TestConnectionSettings(CancellationToken cancellationToken); - Task GenerateThroughputReport(string spVersion, DateTime? reportEndDate, CancellationToken cancellationToken); - Task GetReportGenerationState(CancellationToken cancellationToken); - Task> GetReportMasks(CancellationToken cancellationToken); - Task UpdateReportMasks(List reportMaskUpdates, CancellationToken cancellationToken); + Task> GetThroughputSummary(CancellationToken cancellationToken = default); + Task UpdateUserIndicatorsOnEndpoints(List userIndicatorUpdates, CancellationToken cancellationToken = default); + Task GetThroughputConnectionSettingsInformation(CancellationToken cancellationToken = default); + Task TestConnectionSettings(CancellationToken cancellationToken = default); + Task GenerateThroughputReport(string spVersion, DateTime? reportEndDate, CancellationToken cancellationToken = default); + Task GetReportGenerationState(CancellationToken cancellationToken = default); + Task> GetReportMasks(CancellationToken cancellationToken = default); + Task UpdateReportMasks(List reportMaskUpdates, CancellationToken cancellationToken = default); } } diff --git a/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringService.cs b/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringService.cs index bddab8ab3c..b0dd964a06 100644 --- a/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringService.cs +++ b/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringService.cs @@ -10,7 +10,7 @@ public class MonitoringService(ILicensingDataStore dataStore, IBrokerThroughputQuery? brokerThroughputQuery = null) { - public async Task RecordMonitoringThroughput(byte[] throughputMessage, CancellationToken cancellationToken) + public async Task RecordMonitoringThroughput(byte[] throughputMessage, CancellationToken cancellationToken = default) { RecordEndpointThroughputData? message; using (Stream stream = new MemoryStream(throughputMessage)) @@ -45,7 +45,7 @@ public async Task RecordMonitoringThroughput(byte[] throughputMessage, Cancellat } } - public async Task TestMonitoringConnection(CancellationToken cancellationToken) + public async Task TestMonitoringConnection(CancellationToken cancellationToken = default) { //NOTE can't actually test the monitoring connection apart from seeing if there has been any throughput recorded from Monitoring diff --git a/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringThroughputHostedService.cs b/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringThroughputHostedService.cs index fc5e643bd2..ea8a299e39 100644 --- a/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringThroughputHostedService.cs +++ b/src/Particular.LicensingComponent/MonitoringThroughput/MonitoringThroughputHostedService.cs @@ -16,13 +16,17 @@ async Task Handle(MessageContext message, CancellationToken cancellationToken) { await monitoringService.RecordMonitoringThroughput(message.Body.ToArray(), cancellationToken); } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + throw; + } catch (Exception ex) { logger.LogError(ex, "Error receiving throughput data from Monitoring"); } } - public async Task StartAsync(CancellationToken cancellationToken) + public async Task StartAsync(CancellationToken cancellationToken = default) { logger.LogInformation("Starting {ServiceName}", nameof(MonitoringThroughputHostedService)); @@ -30,7 +34,7 @@ public async Task StartAsync(CancellationToken cancellationToken) await transportInfrastructure.Receivers[ServiceControlSettings.ServiceControlThroughputDataQueue].StartReceive(cancellationToken); } - public async Task StopAsync(CancellationToken cancellationToken) + public async Task StopAsync(CancellationToken cancellationToken = default) { logger.LogInformation("Stopping {ServiceName}", nameof(MonitoringThroughputHostedService)); diff --git a/src/Particular.LicensingComponent/ThroughputCollector.cs b/src/Particular.LicensingComponent/ThroughputCollector.cs index 32f70aaf40..03f11f2a06 100644 --- a/src/Particular.LicensingComponent/ThroughputCollector.cs +++ b/src/Particular.LicensingComponent/ThroughputCollector.cs @@ -16,7 +16,7 @@ public class ThroughputCollector(ILicensingDataStore dataStore, ThroughputSettings throughputSettings, IAuditQuery auditQuery, MonitoringService monitoringService, IEnumerable environmentDataProviders, IBrokerThroughputQuery? throughputQuery = null) : IThroughputCollector { - public async Task GetThroughputConnectionSettingsInformation(CancellationToken cancellationToken) + public async Task GetThroughputConnectionSettingsInformation(CancellationToken cancellationToken = default) { var throughputConnectionSettings = new ThroughputConnectionSettings { @@ -27,7 +27,7 @@ public async Task GetThroughputConnectionSettingsI return await Task.FromResult(throughputConnectionSettings); } - public async Task TestConnectionSettings(CancellationToken cancellationToken) + public async Task TestConnectionSettings(CancellationToken cancellationToken = default) { var tasks = new List(); var brokerTask = Task.FromResult(new ConnectionSettingsTestResult { ConnectionSuccessful = false, ConnectionErrorMessages = [] }); @@ -55,13 +55,13 @@ public async Task TestConnectionSettings(CancellationToke return await Task.FromResult(connectionTestResults); } - public async Task UpdateUserIndicatorsOnEndpoints(List userIndicatorUpdates, CancellationToken cancellationToken) => + public async Task UpdateUserIndicatorsOnEndpoints(List userIndicatorUpdates, CancellationToken cancellationToken = default) => await dataStore.UpdateUserIndicatorOnEndpoints(userIndicatorUpdates, cancellationToken); - public async Task> GetReportMasks(CancellationToken cancellationToken) => await dataStore.GetReportMasks(cancellationToken); - public async Task UpdateReportMasks(List reportMaskUpdates, CancellationToken cancellationToken) => await dataStore.SaveReportMasks(reportMaskUpdates, cancellationToken); + public async Task> GetReportMasks(CancellationToken cancellationToken = default) => await dataStore.GetReportMasks(cancellationToken); + public async Task UpdateReportMasks(List reportMaskUpdates, CancellationToken cancellationToken = default) => await dataStore.SaveReportMasks(reportMaskUpdates, cancellationToken); - public async Task> GetThroughputSummary(CancellationToken cancellationToken) + public async Task> GetThroughputSummary(CancellationToken cancellationToken = default) { var endpointSummaries = new List(); @@ -86,7 +86,7 @@ public async Task> GetThroughputSummary(Cancella return endpointSummaries; } - public async Task GetReportGenerationState(CancellationToken cancellationToken) => + public async Task GetReportGenerationState(CancellationToken cancellationToken = default) => throughputQuery == null ? await GetReportGenerationStateForNonBroker(cancellationToken) : await GetReportGenerationStateForBroker(cancellationToken); @@ -115,7 +115,7 @@ async Task GetReportGenerationStateForNonBroker(Cancellat }; } - public async Task GenerateThroughputReport(string spVersion, DateTime? reportEndDate, CancellationToken cancellationToken) + public async Task GenerateThroughputReport(string spVersion, DateTime? reportEndDate, CancellationToken cancellationToken = default) { var reportMasks = await dataStore.GetReportMasks(cancellationToken); var masker = new Masker([.. reportMasks]); diff --git a/src/Particular.LicensingComponent/WebApi/LicensingController.cs b/src/Particular.LicensingComponent/WebApi/LicensingController.cs index f898c0cc72..99019ae60c 100644 --- a/src/Particular.LicensingComponent/WebApi/LicensingController.cs +++ b/src/Particular.LicensingComponent/WebApi/LicensingController.cs @@ -24,7 +24,7 @@ public LicensingController(IThroughputCollector throughputCollector) [Authorize(Policy = Permissions.ErrorThroughputView)] [Route("endpoints")] [HttpGet] - public async Task> GetEndpointThroughput(CancellationToken cancellationToken) + public async Task> GetEndpointThroughput(CancellationToken cancellationToken = default) { return await throughputCollector.GetThroughputSummary(cancellationToken); } @@ -32,7 +32,7 @@ public async Task> GetEndpointThroughput(Cancell [Authorize(Policy = Permissions.ErrorThroughputManage)] [Route("endpoints/update")] [HttpPost] - public async Task UpdateUserSelectionOnEndpointThroughput(List updateUserIndicators, CancellationToken cancellationToken) + public async Task UpdateUserSelectionOnEndpointThroughput(List updateUserIndicators, CancellationToken cancellationToken = default) { await throughputCollector.UpdateUserIndicatorsOnEndpoints(updateUserIndicators, cancellationToken); return Ok(); @@ -41,7 +41,7 @@ public async Task UpdateUserSelectionOnEndpointThroughput(List CanThroughputReportBeGenerated(CancellationToken cancellationToken) + public async Task CanThroughputReportBeGenerated(CancellationToken cancellationToken = default) { return await throughputCollector.GetReportGenerationState(cancellationToken); } @@ -49,7 +49,7 @@ public async Task CanThroughputReportBeGenerated(Cancella [Authorize(Policy = Permissions.ErrorThroughputView)] [Route("report/file")] [HttpGet] - public async Task GetThroughputReportFile([FromQuery(Name = "spVersion")] string? spVersion, CancellationToken cancellationToken) + public async Task GetThroughputReportFile([FromQuery(Name = "spVersion")] string? spVersion, CancellationToken cancellationToken = default) { var reportStatus = await CanThroughputReportBeGenerated(cancellationToken); if (!reportStatus.ReportCanBeGenerated) @@ -86,7 +86,7 @@ public async Task GetThroughputReportFile([FromQuery(Name = "spVersion")] string [Authorize(Policy = Permissions.ErrorThroughputView)] [Route("settings/info")] [HttpGet] - public async Task GetThroughputSettingsInformation(CancellationToken cancellationToken) + public async Task GetThroughputSettingsInformation(CancellationToken cancellationToken = default) { return await throughputCollector.GetThroughputConnectionSettingsInformation(cancellationToken); } @@ -94,12 +94,12 @@ public async Task GetThroughputSettingsInformation [Authorize(Policy = Permissions.ErrorThroughputView)] [Route("settings/test")] [HttpGet] - public async Task TestThroughputConnectionSettings(CancellationToken cancellationToken) => await throughputCollector.TestConnectionSettings(cancellationToken); + public async Task TestThroughputConnectionSettings(CancellationToken cancellationToken = default) => await throughputCollector.TestConnectionSettings(cancellationToken); [Authorize(Policy = Permissions.ErrorThroughputView)] [Route("settings/masks")] [HttpGet] - public async Task> GetMasks(CancellationToken cancellationToken) + public async Task> GetMasks(CancellationToken cancellationToken = default) { return await throughputCollector.GetReportMasks(cancellationToken); } @@ -107,7 +107,7 @@ public async Task> GetMasks(CancellationToken cancellationToken) [Authorize(Policy = Permissions.ErrorThroughputManage)] [Route("settings/masks/update")] [HttpPost] - public async Task UpdateMasks(List updateMasks, CancellationToken cancellationToken) + public async Task UpdateMasks(List updateMasks, CancellationToken cancellationToken = default) { await throughputCollector.UpdateReportMasks(updateMasks, cancellationToken); return Ok(); diff --git a/src/ServiceControl.AcceptanceTesting/.editorconfig b/src/ServiceControl.AcceptanceTesting/.editorconfig index f3c943025f..cc18ee5f5b 100644 --- a/src/ServiceControl.AcceptanceTesting/.editorconfig +++ b/src/ServiceControl.AcceptanceTesting/.editorconfig @@ -3,9 +3,10 @@ # Justification: Usage is from test projects dotnet_diagnostic.CA2007.severity = none -# Cancellation analyzer debt. These fire because Particular.Analyzers is no longer pinned to 0.9.0. -# They are scheduled work, not accepted exceptions: remove a line once this project has no -# violations of that rule left, and never add a rule back to this list. +# These types sit on NServiceBus.AcceptanceTesting's extension points, which drive them without a +# CancellationToken: IEndpointSetupTemplate, IComponentBehavior/ComponentRunner, and the scenario +# Done/When callbacks whose delegate shapes the framework fixes. A token added here could only ever +# be CancellationToken.None. Everything else in this project takes and forwards one. +[{EndpointTemplates/*.cs,InfrastructureConfig/*.cs,ScenarioWithEndpointBehaviorExtensions.cs,Sequence.cs,DispatchRawMessages.cs}] dotnet_diagnostic.PS0013.severity = none dotnet_diagnostic.PS0018.severity = none -dotnet_diagnostic.PS0019.severity = none diff --git a/src/ServiceControl.AcceptanceTesting/Cors/CorsAssertions.cs b/src/ServiceControl.AcceptanceTesting/Cors/CorsAssertions.cs index d92d55af6d..2c9e4189dc 100644 --- a/src/ServiceControl.AcceptanceTesting/Cors/CorsAssertions.cs +++ b/src/ServiceControl.AcceptanceTesting/Cors/CorsAssertions.cs @@ -2,6 +2,7 @@ namespace ServiceControl.AcceptanceTesting.Cors { using System.Net; using System.Net.Http; + using System.Threading; using System.Threading.Tasks; using NUnit.Framework; @@ -22,13 +23,14 @@ public static class CorsAssertions public static async Task SendPreflightRequest( HttpClient httpClient, string origin, - string requestMethod = "GET") + string requestMethod = "GET", + CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(HttpMethod.Options, "/api"); request.Headers.Add("Origin", origin); request.Headers.Add("Access-Control-Request-Method", requestMethod); - return await httpClient.SendAsync(request); + return await httpClient.SendAsync(request, cancellationToken); } /// @@ -37,12 +39,13 @@ public static async Task SendPreflightRequest( public static async Task SendRequestWithOrigin( HttpClient httpClient, string origin, - string endpoint = "/api") + string endpoint = "/api", + CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(HttpMethod.Get, endpoint); request.Headers.Add("Origin", origin); - return await httpClient.SendAsync(request); + return await httpClient.SendAsync(request, cancellationToken); } /// diff --git a/src/ServiceControl.AcceptanceTesting/EndpointConfigurationExtensions.cs b/src/ServiceControl.AcceptanceTesting/EndpointConfigurationExtensions.cs index 8998e768d7..bcce34bc4f 100644 --- a/src/ServiceControl.AcceptanceTesting/EndpointConfigurationExtensions.cs +++ b/src/ServiceControl.AcceptanceTesting/EndpointConfigurationExtensions.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; + using System.Threading; using System.Threading.Tasks; using InfrastructureConfig; using NServiceBus; @@ -54,7 +55,7 @@ IEnumerable GetNestedTypeRecursive(Type rootType, Type builderType) } } - public static async Task DefinePersistence(this EndpointConfiguration config, RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizationConfiguration) + public static async Task DefinePersistence(this EndpointConfiguration config, RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizationConfiguration, CancellationToken cancellationToken = default) { var persistenceConfiguration = new ConfigureEndpointInMemoryPersistence(); await persistenceConfiguration.Configure(endpointCustomizationConfiguration.EndpointName, config, runDescriptor.Settings, endpointCustomizationConfiguration.PublisherMetadata); diff --git a/src/ServiceControl.AcceptanceTesting/ForwardedHeaders/ForwardedHeadersAssertions.cs b/src/ServiceControl.AcceptanceTesting/ForwardedHeaders/ForwardedHeadersAssertions.cs index a8da121863..a4f90a49ba 100644 --- a/src/ServiceControl.AcceptanceTesting/ForwardedHeaders/ForwardedHeadersAssertions.cs +++ b/src/ServiceControl.AcceptanceTesting/ForwardedHeaders/ForwardedHeadersAssertions.cs @@ -2,6 +2,7 @@ namespace ServiceControl.AcceptanceTesting.ForwardedHeaders { using System.Net.Http; using System.Text.Json; + using System.Threading; using System.Threading.Tasks; using NUnit.Framework; @@ -20,7 +21,8 @@ public static async Task GetRequestInfo( string xForwardedFor = null, string xForwardedProto = null, string xForwardedHost = null, - string testRemoteIp = null) + string testRemoteIp = null, + CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(HttpMethod.Get, "/debug/request-info"); @@ -41,10 +43,10 @@ public static async Task GetRequestInfo( request.Headers.Add(TestRemoteIpMiddleware.HeaderName, testRemoteIp); } - var response = await httpClient.SendAsync(request); + var response = await httpClient.SendAsync(request, cancellationToken); _ = response.EnsureSuccessStatusCode(); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); return JsonSerializer.Deserialize(content, serializerOptions); } diff --git a/src/ServiceControl.AcceptanceTesting/HttpClientExtensions.cs b/src/ServiceControl.AcceptanceTesting/HttpClientExtensions.cs index 861fbe4045..f30d41518b 100644 --- a/src/ServiceControl.AcceptanceTesting/HttpClientExtensions.cs +++ b/src/ServiceControl.AcceptanceTesting/HttpClientExtensions.cs @@ -1,11 +1,12 @@ namespace ServiceControl.AcceptanceTesting { using System.Net.Http; + using System.Threading; using System.Threading.Tasks; public static class HttpClientExtensions { - public static async Task PatchAsync(this HttpClient client, string requestUri, HttpContent iContent) + public static async Task PatchAsync(this HttpClient client, string requestUri, HttpContent iContent, CancellationToken cancellationToken = default) { var method = new HttpMethod("PATCH"); var request = new HttpRequestMessage(method, requestUri) @@ -13,7 +14,7 @@ public static async Task PatchAsync(this HttpClient client, Content = iContent }; - var response = await client.SendAsync(request); + var response = await client.SendAsync(request, cancellationToken); return response; } diff --git a/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs b/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs index 7e5ebde17f..9f8c8ee140 100644 --- a/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs +++ b/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs @@ -6,16 +6,17 @@ namespace ServiceControl.AcceptanceTesting using System.Net; using System.Net.Http; using System.Net.Http.Json; + using System.Threading; using System.Threading.Tasks; public static class HttpExtensions { - public static async Task Put(this IAcceptanceTestInfrastructureProvider provider, string url, T payload = null, Func requestHasFailed = null) where T : class + public static async Task Put(this IAcceptanceTestInfrastructureProvider provider, string url, T payload = null, Func requestHasFailed = null, CancellationToken cancellationToken = default) where T : class { requestHasFailed ??= statusCode => statusCode is not HttpStatusCode.OK and not HttpStatusCode.Accepted; var httpClient = provider.HttpClient; - var response = await httpClient.PutAsJsonAsync(url, payload, provider.SerializerOptions); + var response = await httpClient.PutAsJsonAsync(url, payload, provider.SerializerOptions, cancellationToken); if (requestHasFailed(response.StatusCode)) { @@ -23,24 +24,24 @@ public static async Task Put(this IAcceptanceTestInfrastructureProvider provi } } - public static Task GetRaw(this IAcceptanceTestInfrastructureProvider provider, string url) + public static Task GetRaw(this IAcceptanceTestInfrastructureProvider provider, string url, CancellationToken cancellationToken = default) { var httpClient = provider.HttpClient; - return httpClient.GetAsync(url); + return httpClient.GetAsync(url, cancellationToken); } - public static Task Options(this IAcceptanceTestInfrastructureProvider provider, string url) + public static Task Options(this IAcceptanceTestInfrastructureProvider provider, string url, CancellationToken cancellationToken = default) { var httpClient = provider.HttpClient; var request = new HttpRequestMessage(HttpMethod.Options, url); - return httpClient.SendAsync(request); + return httpClient.SendAsync(request, cancellationToken); } - public static async Task> TryGetMany(this IAcceptanceTestInfrastructureProvider provider, string url, Predicate condition = null) where T : class + public static async Task> TryGetMany(this IAcceptanceTestInfrastructureProvider provider, string url, Predicate condition = null, CancellationToken cancellationToken = default) where T : class { condition ??= _ => true; - var response = await provider.GetInternal>(url); + var response = await provider.GetInternal>(url, cancellationToken); if (response == null || !response.Any(m => condition(m))) { @@ -50,25 +51,25 @@ public static async Task> TryGetMany(this IAcceptanceTestInfras return ManyResult.New(true, response.Where(m => condition(m)).ToList()); } - public static async Task Patch(this IAcceptanceTestInfrastructureProvider provider, string url, T payload = null) where T : class + public static async Task Patch(this IAcceptanceTestInfrastructureProvider provider, string url, T payload = null, CancellationToken cancellationToken = default) where T : class { var httpClient = provider.HttpClient; - var response = await httpClient.PatchAsJsonAsync(url, payload, provider.SerializerOptions); + var response = await httpClient.PatchAsJsonAsync(url, payload, provider.SerializerOptions, cancellationToken); if (!response.IsSuccessStatusCode) { - var body = await response.Content.ReadAsStringAsync(); + var body = await response.Content.ReadAsStringAsync(cancellationToken); throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} - {body}"); } return response.StatusCode; } - public static async Task> TryGet(this IAcceptanceTestInfrastructureProvider provider, string url, Predicate condition = null) where T : class + public static async Task> TryGet(this IAcceptanceTestInfrastructureProvider provider, string url, Predicate condition = null, CancellationToken cancellationToken = default) where T : class { condition ??= _ => true; - var response = await provider.GetInternal(url); + var response = await provider.GetInternal(url, cancellationToken); if (response == null || !condition(response)) { @@ -78,11 +79,11 @@ public static async Task> TryGet(this IAcceptanceTestInfrastr return SingleResult.New(response); } - public static async Task> TryGet(this IAcceptanceTestInfrastructureProvider provider, string url, Func> condition) where T : class + public static async Task> TryGet(this IAcceptanceTestInfrastructureProvider provider, string url, Func> condition, CancellationToken cancellationToken = default) where T : class { - var response = await provider.GetInternal(url); + var response = await provider.GetInternal(url, cancellationToken); - if (response == null || !await condition(response)) + if (response == null || !await condition(response, cancellationToken)) { return SingleResult.Empty; } @@ -90,11 +91,11 @@ public static async Task> TryGet(this IAcceptanceTestInfrastr return SingleResult.New(response); } - public static async Task> TryGetSingle(this IAcceptanceTestInfrastructureProvider provider, string url, Predicate condition = null) where T : class + public static async Task> TryGetSingle(this IAcceptanceTestInfrastructureProvider provider, string url, Predicate condition = null, CancellationToken cancellationToken = default) where T : class { condition ??= _ => true; - var response = await provider.GetInternal>(url); + var response = await provider.GetInternal>(url, cancellationToken); T item = null; if (response != null) { @@ -116,17 +117,17 @@ public static async Task> TryGetSingle(this IAcceptanceTestIn return SingleResult.Empty; } - public static async Task Get(this IAcceptanceTestInfrastructureProvider provider, string url) + public static async Task Get(this IAcceptanceTestInfrastructureProvider provider, string url, CancellationToken cancellationToken = default) { var httpClient = provider.HttpClient; - var response = await httpClient.GetAsync(url); + var response = await httpClient.GetAsync(url, cancellationToken); return response.StatusCode; } - public static async Task Post(this IAcceptanceTestInfrastructureProvider provider, string url, T payload = null, Func requestHasFailed = null) where T : class + public static async Task Post(this IAcceptanceTestInfrastructureProvider provider, string url, T payload = null, Func requestHasFailed = null, CancellationToken cancellationToken = default) where T : class { var httpClient = provider.HttpClient; - var response = await httpClient.PostAsJsonAsync(url, payload, provider.SerializerOptions); + var response = await httpClient.PostAsJsonAsync(url, payload, provider.SerializerOptions, cancellationToken); if (requestHasFailed != null) { @@ -140,39 +141,39 @@ public static async Task Post(this IAcceptanceTestInfrastructureProvider prov if (!response.IsSuccessStatusCode) { - var body = await response.Content.ReadAsStringAsync(); + var body = await response.Content.ReadAsStringAsync(cancellationToken); throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} - {body}"); } } - public static async Task Delete(this IAcceptanceTestInfrastructureProvider provider, string url) + public static async Task Delete(this IAcceptanceTestInfrastructureProvider provider, string url, CancellationToken cancellationToken = default) { var httpClient = provider.HttpClient; - var response = await httpClient.DeleteAsync(url); + var response = await httpClient.DeleteAsync(url, cancellationToken); if (!response.IsSuccessStatusCode) { - var body = await response.Content.ReadAsStringAsync(); + var body = await response.Content.ReadAsStringAsync(cancellationToken); throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} - {body}"); } } - public static async Task DownloadData(this IAcceptanceTestInfrastructureProvider provider, string url, HttpStatusCode successCode = HttpStatusCode.OK) + public static async Task DownloadData(this IAcceptanceTestInfrastructureProvider provider, string url, HttpStatusCode successCode = HttpStatusCode.OK, CancellationToken cancellationToken = default) { var httpClient = provider.HttpClient; - var response = await httpClient.GetAsync(url); + var response = await httpClient.GetAsync(url, cancellationToken); if (response.StatusCode != successCode) { throw new Exception($"Expected status code of {successCode}, but instead got {response.StatusCode}."); } - return await response.Content.ReadAsByteArrayAsync(); + return await response.Content.ReadAsByteArrayAsync(cancellationToken); } - static async Task GetInternal(this IAcceptanceTestInfrastructureProvider provider, string url) where T : class + static async Task GetInternal(this IAcceptanceTestInfrastructureProvider provider, string url, CancellationToken cancellationToken) where T : class { - var response = await provider.GetRaw(url); + var response = await provider.GetRaw(url, cancellationToken); //for now if (response.StatusCode is HttpStatusCode.NotFound or HttpStatusCode.NoContent or HttpStatusCode.ServiceUnavailable) @@ -183,12 +184,12 @@ static async Task GetInternal(this IAcceptanceTestInfrastructureProvider p if (response.StatusCode != HttpStatusCode.OK) { - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); LogRequest(response.ReasonPhrase + content); throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} {Environment.NewLine} {content}"); } - var payload = await response.Content.ReadFromJsonAsync(provider.SerializerOptions); + var payload = await response.Content.ReadFromJsonAsync(provider.SerializerOptions, cancellationToken); LogRequest(); return payload; diff --git a/src/ServiceControl.AcceptanceTesting/OpenIdConnect/OpenIdConnectAssertions.cs b/src/ServiceControl.AcceptanceTesting/OpenIdConnect/OpenIdConnectAssertions.cs index b48cc3ea87..54d36581b2 100644 --- a/src/ServiceControl.AcceptanceTesting/OpenIdConnect/OpenIdConnectAssertions.cs +++ b/src/ServiceControl.AcceptanceTesting/OpenIdConnect/OpenIdConnectAssertions.cs @@ -4,6 +4,7 @@ namespace ServiceControl.AcceptanceTesting.OpenIdConnect using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; + using System.Threading; using System.Threading.Tasks; using NUnit.Framework; @@ -74,9 +75,9 @@ public static void AssertWwwAuthenticateHeader(HttpResponseMessage response) /// /// Asserts that the response body contains the expected error response format. /// - public static async Task AssertAuthErrorResponse(HttpResponseMessage response, string expectedError = "unauthorized") + public static async Task AssertAuthErrorResponse(HttpResponseMessage response, string expectedError = "unauthorized", CancellationToken cancellationToken = default) { - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); Assert.That(content, Is.Not.Null.And.Not.Empty, "Response should have a body"); var jsonDoc = JsonDocument.Parse(content); @@ -107,12 +108,13 @@ public static async Task AssertAuthConfigurationResponse( string expectedAudience = null, string expectedApiScopes = null, string expectedScopes = null, - bool expectedRoleBasedAuthorizationEnabled = false) + bool expectedRoleBasedAuthorizationEnabled = false, + CancellationToken cancellationToken = default) { Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), "Authentication configuration endpoint should return 200 OK"); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var jsonDoc = JsonDocument.Parse(content); var root = jsonDoc.RootElement; @@ -201,11 +203,12 @@ public static async Task SendRequestWithBearerToken( HttpClient client, HttpMethod method, string path, - string token) + string token, + CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(method, path); request.Headers.Authorization = CreateBearerToken(token); - return await client.SendAsync(request); + return await client.SendAsync(request, cancellationToken); } /// @@ -214,10 +217,11 @@ public static async Task SendRequestWithBearerToken( public static async Task SendRequestWithoutAuth( HttpClient client, HttpMethod method, - string path) + string path, + CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(method, path); - return await client.SendAsync(request); + return await client.SendAsync(request, cancellationToken); } } } diff --git a/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs b/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs index 745bb3bcf5..8f02d3ea2e 100644 --- a/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs +++ b/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs @@ -104,11 +104,12 @@ class Runner( public override Task ComponentsStarted(CancellationToken cancellationToken = default) { tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + var checkToken = tokenSource.Token; checkTask = Task.Run(async () => { try { - while (!tokenSource.IsCancellationRequested) + while (!checkToken.IsCancellationRequested) { if (await isDone(scenarioContext)) { @@ -116,14 +117,18 @@ public override Task ComponentsStarted(CancellationToken cancellationToken = def return; } - await Task.Delay(100, tokenSource.Token); + await Task.Delay(100, checkToken); } } + catch (OperationCanceledException) when (checkToken.IsCancellationRequested) + { + // Stopping the run cancels the poll; that is not a test failure + } catch (Exception e) { setException(ExceptionDispatchInfo.Capture(e)); } - }, tokenSource.Token); + }, checkToken); return Task.CompletedTask; } diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs b/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs index 462c2ab607..3157f0a53d 100644 --- a/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs +++ b/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs @@ -34,7 +34,7 @@ public async Task Cleanup(CancellationToken cancellationToken = default) return; } using var _ = await UseDatabaseLifecycleLock(cancellationToken); - await databaseInstance.DeleteDatabase(databaseName); + await databaseInstance.DeleteDatabase(databaseName, cancellationToken); } /// diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig b/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig index b9cef92e2f..ff993b49bb 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig +++ b/src/ServiceControl.Audit.Persistence.RavenDB/.editorconfig @@ -2,9 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -# WaitForLicenseOrThrow passes only the linked cts.Token into its try, so PS0020 cannot recognise a -# filter on the caller's token. Removing this needs the license-check exception mapping reworked, not -# a token added, so it is deliberately scoped to the one file rather than the project. -[LicenseStatusCheck.cs] -dotnet_diagnostic.PS0020.severity = none diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index 935e948875..9b8415ab9e 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -37,7 +37,9 @@ public static async Task WaitForLicenseOrThrow(IDocumentStore documentStore, Can await Task.Delay(200, cts.Token); } } +#pragma warning disable PS0020 // The try runs on the linked cts.Token, which is always cancelled in the timeout case this maps. Filtering on it instead of the caller's token would make the filter unreachable catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) +#pragma warning restore PS0020 { throw new InvalidOperationException("Cannot validate the current RavenDB license. Please, contact support"); } diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/.editorconfig b/src/ServiceControl.Persistence.EFCore.PostgreSql/.editorconfig index ea99d7cc09..fc68ac3228 100644 --- a/src/ServiceControl.Persistence.EFCore.PostgreSql/.editorconfig +++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/.editorconfig @@ -3,11 +3,6 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none -# Cancellation analyzer debt. These fire because Particular.Analyzers is no longer pinned to 0.9.0. -# They are scheduled work, not accepted exceptions: remove a line once this project has no -# violations of that rule left, and never add a rule back to this list. -dotnet_diagnostic.PS0003.severity = none - # Disable style rules for auto-generated EF migrations [Migrations/**.cs] dotnet_diagnostic.IDE0065.severity = none diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlDialect.cs b/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlDialect.cs index d177ef3f59..385b61ddc5 100644 --- a/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlDialect.cs +++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlDialect.cs @@ -7,7 +7,7 @@ namespace ServiceControl.Persistence.EFCore.PostgreSql; abstract class PostgreSqlDialect { - protected static async Task Execute(ServiceControlDbContext dbContext, string sql, IEnumerable rows, CancellationToken cancellationToken) + protected static async Task Execute(ServiceControlDbContext dbContext, string sql, IEnumerable rows, CancellationToken cancellationToken = default) { await using var command = dbContext.Database.GetDbConnection().CreateCommand(); command.Transaction = (dbContext.Database.CurrentTransaction diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlFailedMessageIngestionSqlDialect.cs b/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlFailedMessageIngestionSqlDialect.cs index 17184e1aeb..f1c9f0a0be 100644 --- a/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlFailedMessageIngestionSqlDialect.cs +++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlFailedMessageIngestionSqlDialect.cs @@ -12,7 +12,7 @@ namespace ServiceControl.Persistence.EFCore.PostgreSql; // atomic statement. Rows are chunked to keep statement texts down to a few reusable shapes. class PostgreSqlFailedMessageIngestionSqlDialect : PostgreSqlDialect, IFailedMessageIngestionSqlDialect { - public async Task UpsertFailedMessages(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task UpsertFailedMessages(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { foreach (var chunk in rows.Chunk(MaxRowsPerStatement)) { @@ -29,7 +29,7 @@ INSERT INTO failed_messages ({FailedMessageColumnList}) } } - public async Task InsertGroups(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task InsertGroups(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { foreach (var chunk in rows.Chunk(MaxRowsPerStatement)) { @@ -46,7 +46,7 @@ ON CONFLICT (failed_message_unique_id, group_id) DO NOTHING } } - public async Task InsertMissingKnownEndpoints(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task InsertMissingKnownEndpoints(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { foreach (var chunk in rows.Chunk(MaxRowsPerStatement)) { diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlRetryBatchSqlDialect.cs b/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlRetryBatchSqlDialect.cs index a15cb17c58..3de74ce12a 100644 --- a/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlRetryBatchSqlDialect.cs +++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/PostgreSqlRetryBatchSqlDialect.cs @@ -6,7 +6,7 @@ namespace ServiceControl.Persistence.EFCore.PostgreSql; class PostgreSqlRetryBatchSqlDialect : PostgreSqlDialect, IRetryBatchSqlDialect { - public async Task InsertMissingRetryClaims(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task InsertMissingRetryClaims(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { foreach (var chunk in rows.Chunk(MaxRowsPerStatement)) { diff --git a/src/ServiceControl.Persistence.EFCore.SqlServer/.editorconfig b/src/ServiceControl.Persistence.EFCore.SqlServer/.editorconfig index ea99d7cc09..fc68ac3228 100644 --- a/src/ServiceControl.Persistence.EFCore.SqlServer/.editorconfig +++ b/src/ServiceControl.Persistence.EFCore.SqlServer/.editorconfig @@ -3,11 +3,6 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none -# Cancellation analyzer debt. These fire because Particular.Analyzers is no longer pinned to 0.9.0. -# They are scheduled work, not accepted exceptions: remove a line once this project has no -# violations of that rule left, and never add a rule back to this list. -dotnet_diagnostic.PS0003.severity = none - # Disable style rules for auto-generated EF migrations [Migrations/**.cs] dotnet_diagnostic.IDE0065.severity = none diff --git a/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerDialect.cs b/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerDialect.cs index 6a2ff7de55..a053469147 100644 --- a/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerDialect.cs +++ b/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerDialect.cs @@ -8,7 +8,7 @@ namespace ServiceControl.Persistence.EFCore.SqlServer; abstract class SqlServerDialect { - protected static async Task Execute(ServiceControlDbContext dbContext, string sql, IEnumerable rows, CancellationToken cancellationToken) + protected static async Task Execute(ServiceControlDbContext dbContext, string sql, IEnumerable rows, CancellationToken cancellationToken = default) { await using var command = dbContext.Database.GetDbConnection().CreateCommand(); command.Transaction = (dbContext.Database.CurrentTransaction diff --git a/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerFailedMessageIngestionSqlDialect.cs b/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerFailedMessageIngestionSqlDialect.cs index 6206d3bfa4..cb8f4c9f53 100644 --- a/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerFailedMessageIngestionSqlDialect.cs +++ b/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerFailedMessageIngestionSqlDialect.cs @@ -12,7 +12,7 @@ namespace ServiceControl.Persistence.EFCore.SqlServer; // statement texts down to a few reusable shapes. class SqlServerFailedMessageIngestionSqlDialect : SqlServerDialect, IFailedMessageIngestionSqlDialect { - public async Task UpsertFailedMessages(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task UpsertFailedMessages(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { var maxRowsPerStatement = MaxRowsPerStatement(FailedMessageColumns.Length); foreach (var chunk in rows.Chunk(maxRowsPerStatement)) @@ -34,7 +34,7 @@ WHEN NOT MATCHED THEN INSERT ({FailedMessageColumnList}) } } - public async Task InsertGroups(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task InsertGroups(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { var maxRowsPerStatement = MaxRowsPerStatement(4); foreach (var chunk in rows.Chunk(maxRowsPerStatement)) @@ -55,7 +55,7 @@ WHEN NOT MATCHED THEN INSERT ([FailedMessageUniqueId], [GroupId], [Title], [Type } } - public async Task InsertMissingKnownEndpoints(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task InsertMissingKnownEndpoints(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { var maxRowsPerStatement = MaxRowsPerStatement(5); foreach (var chunk in rows.Chunk(maxRowsPerStatement)) diff --git a/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerRetryBatchSqlDialect.cs b/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerRetryBatchSqlDialect.cs index 0774e5c64b..1e8de7a9c5 100644 --- a/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerRetryBatchSqlDialect.cs +++ b/src/ServiceControl.Persistence.EFCore.SqlServer/SqlServerRetryBatchSqlDialect.cs @@ -6,7 +6,7 @@ namespace ServiceControl.Persistence.EFCore.SqlServer; class SqlServerRetryBatchSqlDialect : SqlServerDialect, IRetryBatchSqlDialect { - public async Task InsertMissingRetryClaims(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken) + public async Task InsertMissingRetryClaims(ServiceControlDbContext dbContext, IReadOnlyList rows, CancellationToken cancellationToken = default) { var maxRowsPerStatement = MaxRowsPerStatement(3); foreach (var chunk in rows.Chunk(maxRowsPerStatement)) diff --git a/src/ServiceControl.RavenDB/.editorconfig b/src/ServiceControl.RavenDB/.editorconfig index 522a310bff..ff993b49bb 100644 --- a/src/ServiceControl.RavenDB/.editorconfig +++ b/src/ServiceControl.RavenDB/.editorconfig @@ -2,9 +2,3 @@ # Justification: ServiceControl app has no synchronization context dotnet_diagnostic.CA2007.severity = none - -# Cancellation analyzer debt. These fire because Particular.Analyzers is no longer pinned to 0.9.0. -# They are scheduled work, not accepted exceptions: remove a line once this project has no -# violations of that rule left, and never add a rule back to this list. -dotnet_diagnostic.PS0003.severity = none -dotnet_diagnostic.PS0018.severity = none diff --git a/src/ServiceControl.RavenDB/EmbeddedDatabase.cs b/src/ServiceControl.RavenDB/EmbeddedDatabase.cs index f0026a51d7..a2079816eb 100644 --- a/src/ServiceControl.RavenDB/EmbeddedDatabase.cs +++ b/src/ServiceControl.RavenDB/EmbeddedDatabase.cs @@ -165,7 +165,7 @@ void OnServerProcessExited(object? sender, ServerProcessExitedEventArgs _) } } - public async Task Connect(CancellationToken cancellationToken) + public async Task Connect(CancellationToken cancellationToken = default) { var dbOptions = new DatabaseOptions(configuration.Name) { @@ -180,16 +180,16 @@ public async Task Connect(CancellationToken cancellationToken) return store; } - public async Task DeleteDatabase(string dbName) + public async Task DeleteDatabase(string dbName, CancellationToken cancellationToken = default) { using var store = await EmbeddedServer.Instance.GetDocumentStoreAsync(new DatabaseOptions(dbName) { SkipCreatingDatabase = true - }); - await store.Maintenance.Server.SendAsync(new DeleteDatabasesOperation(dbName, true)); + }, cancellationToken); + await store.Maintenance.Server.SendAsync(new DeleteDatabasesOperation(dbName, true), cancellationToken); } - public async Task Stop(CancellationToken cancellationToken) + public async Task Stop(CancellationToken cancellationToken = default) { logger.LogDebug("Stopping RavenDB server"); EmbeddedServer.Instance.ServerProcessExited -= OnServerProcessExited;