diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 73671fb7ec..3641c5547c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: [ windows-2022 ]
- test-category: [ Default, SqlServer, AzureServiceBus, RabbitMQ, AzureStorageQueues, MSMQ, SQS ]
+ test-category: [ Default, SqlServer, AzureServiceBus, RabbitMQ, AzureStorageQueues, MSMQ, SQS, Raven35Acceptance ]
include:
- os: windows-2022
os-name: Windows
diff --git a/.gitignore b/.gitignore
index 190ac12bc6..4ae2510ff1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,3 +100,6 @@ src/scaffolding.config
# Visual Studio Code
.vscode
+
+
+.transport
diff --git a/src/Persisters.Primary.Includes.props b/src/Persisters.Primary.Includes.props
new file mode 100644
index 0000000000..980c909b60
--- /dev/null
+++ b/src/Persisters.Primary.Includes.props
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ServiceControl.AcceptanceTesting/DispatchRawMessages.cs b/src/ServiceControl.AcceptanceTesting/DispatchRawMessages.cs
index d6f3145f93..810f2824da 100644
--- a/src/ServiceControl.AcceptanceTesting/DispatchRawMessages.cs
+++ b/src/ServiceControl.AcceptanceTesting/DispatchRawMessages.cs
@@ -51,7 +51,7 @@ public DispatchTask(IDispatchMessages dispatcher, Func oper
protected override async Task OnStart(IMessageSession session)
{
- await before(session).ConfigureAwait(false);
+ await before(session);
var operations = operationFactory();
foreach (var op in operations.UnicastTransportOperations)
{
@@ -63,9 +63,8 @@ protected override async Task OnStart(IMessageSession session)
op.Message.Headers["SC.SessionID"] = scenarioContext.TestRunId.ToString();
}
- await dispatchMessages.Dispatch(operations, new TransportTransaction(), new ContextBag())
- .ConfigureAwait(false);
- await after(session).ConfigureAwait(false);
+ await dispatchMessages.Dispatch(operations, new TransportTransaction(), new ContextBag());
+ await after(session);
}
protected override Task OnStop(IMessageSession session)
diff --git a/src/ServiceControl.AcceptanceTesting/EndpointTemplates/DefaultServerBase.cs b/src/ServiceControl.AcceptanceTesting/EndpointTemplates/DefaultServerBase.cs
index d6098a04dc..4fc9f33368 100644
--- a/src/ServiceControl.AcceptanceTesting/EndpointTemplates/DefaultServerBase.cs
+++ b/src/ServiceControl.AcceptanceTesting/EndpointTemplates/DefaultServerBase.cs
@@ -51,7 +51,7 @@ public async Task GetConfiguration(RunDescriptor runDescr
runDescriptor.OnTestCompleted(_ => endpointTestExecutionConfiguration.Cleanup());
endpointConfiguration.RegisterComponentsAndInheritanceHierarchy(runDescriptor);
- await endpointConfiguration.DefinePersistence(runDescriptor, endpointCustomizations).ConfigureAwait(false);
+ await endpointConfiguration.DefinePersistence(runDescriptor, endpointCustomizations);
typeof(ScenarioContext).GetProperty("CurrentEndpoint", BindingFlags.Static | BindingFlags.NonPublic).SetValue(runDescriptor.ScenarioContext, endpointCustomizations.EndpointName);
diff --git a/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs b/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs
index eb2f6ba421..9972ecb3ce 100644
--- a/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs
+++ b/src/ServiceControl.AcceptanceTesting/HttpExtensions.cs
@@ -64,7 +64,7 @@ public static async Task> TryGetMany(this IAcceptanceTestInfras
condition = _ => true;
}
- var response = await provider.GetInternal>(url).ConfigureAwait(false);
+ var response = await provider.GetInternal>(url);
if (response == null || !response.Any(m => condition(m)))
{
@@ -83,13 +83,13 @@ public static async Task Patch(this IAcceptanceTestInfrastruc
var json = JsonConvert.SerializeObject(payload, provider.SerializerSettings);
var httpClient = provider.HttpClient;
- var response = await httpClient.PatchAsync(url, new StringContent(json, null, "application/json")).ConfigureAwait(false);
+ var response = await httpClient.PatchAsync(url, new StringContent(json, null, "application/json"));
Console.WriteLine($"PATCH - {url} - {(int)response.StatusCode}");
if (!response.IsSuccessStatusCode)
{
- var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var body = await response.Content.ReadAsStringAsync();
throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} - {body}");
}
@@ -103,7 +103,7 @@ public static async Task> TryGet(this IAcceptanceTestInfrastr
condition = _ => true;
}
- var response = await provider.GetInternal(url).ConfigureAwait(false);
+ var response = await provider.GetInternal(url);
if (response == null || !condition(response))
{
@@ -115,9 +115,9 @@ public static async Task> TryGet(this IAcceptanceTestInfrastr
public static async Task> TryGet(this IAcceptanceTestInfrastructureProvider provider, string url, Func> condition) where T : class
{
- var response = await provider.GetInternal(url).ConfigureAwait(false);
+ var response = await provider.GetInternal(url);
- if (response == null || !await condition(response).ConfigureAwait(false))
+ if (response == null || !await condition(response))
{
return SingleResult.Empty;
}
@@ -162,7 +162,7 @@ public static async Task Get(this IAcceptanceTestInfrastructureP
}
var httpClient = provider.HttpClient;
- var response = await httpClient.GetAsync(url).ConfigureAwait(false);
+ var response = await httpClient.GetAsync(url);
Console.WriteLine($"{response.RequestMessage.Method} - {url} - {(int)response.StatusCode}");
@@ -178,7 +178,7 @@ public static async Task Post(this IAcceptanceTestInfrastructureProvider prov
var json = JsonConvert.SerializeObject(payload, provider.SerializerSettings);
var httpClient = provider.HttpClient;
- var response = await httpClient.PostAsync(url, new StringContent(json, null, "application/json")).ConfigureAwait(false);
+ var response = await httpClient.PostAsync(url, new StringContent(json, null, "application/json"));
Console.WriteLine($"{response.RequestMessage.Method} - {url} - {(int)response.StatusCode}");
@@ -194,7 +194,7 @@ public static async Task Post(this IAcceptanceTestInfrastructureProvider prov
if (!response.IsSuccessStatusCode)
{
- var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var body = await response.Content.ReadAsStringAsync();
throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} - {body}");
}
}
@@ -238,7 +238,7 @@ public static async Task DownloadData(this IAcceptanceTestInfrastructure
static async Task GetInternal(this IAcceptanceTestInfrastructureProvider provider, string url) where T : class
{
- var response = await provider.GetRaw(url).ConfigureAwait(false);
+ var response = await provider.GetRaw(url);
//for now
if (response.StatusCode == HttpStatusCode.NotFound || response.StatusCode == HttpStatusCode.ServiceUnavailable)
@@ -254,7 +254,7 @@ static async Task GetInternal(this IAcceptanceTestInfrastructureProvider p
throw new InvalidOperationException($"Call failed: {(int)response.StatusCode} - {response.ReasonPhrase} {Environment.NewLine} {content}");
}
- var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var body = await response.Content.ReadAsStringAsync();
LogRequest();
return JsonConvert.DeserializeObject(body, provider.SerializerSettings);
diff --git a/src/ServiceControl.AcceptanceTesting/InfrastructureConfig/ConfigureEndpointLearningTransport.cs b/src/ServiceControl.AcceptanceTesting/InfrastructureConfig/ConfigureEndpointLearningTransport.cs
index e3cacdb532..9c174981d0 100644
--- a/src/ServiceControl.AcceptanceTesting/InfrastructureConfig/ConfigureEndpointLearningTransport.cs
+++ b/src/ServiceControl.AcceptanceTesting/InfrastructureConfig/ConfigureEndpointLearningTransport.cs
@@ -9,6 +9,14 @@
public class ConfigureEndpointLearningTransport : ITransportIntegration
{
+ public ConfigureEndpointLearningTransport()
+ {
+ var relativePath = Path.Combine(TestContext.CurrentContext.TestDirectory, @"..", "..", "..", ".transport");
+ ConnectionString = Path.GetFullPath(relativePath);
+ }
+
+ public string ConnectionString { get; set; }
+
public Task Configure(string endpointName, EndpointConfiguration configuration, RunSettings settings, PublisherMetadata publisherMetadata)
{
Directory.CreateDirectory(ConnectionString);
@@ -24,7 +32,13 @@ public Task Cleanup()
{
if (Directory.Exists(ConnectionString))
{
- Directory.Delete(ConnectionString, true);
+ try
+ {
+ Directory.Delete(ConnectionString, true);
+ }
+ catch (DirectoryNotFoundException)
+ {
+ }
}
return Task.FromResult(0);
@@ -32,6 +46,5 @@ public Task Cleanup()
public string Name => "Learning";
public string TypeName => $"{typeof(LearningTransportCustomization).AssemblyQualifiedName}";
- public string ConnectionString { get; set; } = Path.Combine(TestContext.CurrentContext.TestDirectory, @"..\..\..\.transport");
}
}
\ No newline at end of file
diff --git a/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs b/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs
index 62901bba3e..09acd6124c 100644
--- a/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs
+++ b/src/ServiceControl.AcceptanceTesting/NServiceBusAcceptanceTest.cs
@@ -10,6 +10,7 @@
/// Base class for all the NSB test that sets up our conventions
///
[TestFixture]
+ [FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
public abstract partial class NServiceBusAcceptanceTest
{
[SetUp]
diff --git a/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs b/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs
index 38b166c70e..b14ecad05f 100644
--- a/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs
+++ b/src/ServiceControl.AcceptanceTesting/ScenarioWithEndpointBehaviorExtensions.cs
@@ -109,13 +109,13 @@ public override Task ComponentsStarted(CancellationToken cancellationToken = def
{
while (!tokenSource.IsCancellationRequested)
{
- if (await isDone(scenarioContext).ConfigureAwait(false))
+ if (await isDone(scenarioContext))
{
setDone();
return;
}
- await Task.Delay(100, tokenSource.Token).ConfigureAwait(false);
+ await Task.Delay(100, tokenSource.Token);
}
}
catch (Exception e)
@@ -136,7 +136,7 @@ public override async Task Stop()
tokenSource.Cancel();
try
{
- await checkTask.ConfigureAwait(false);
+ await checkTask;
}
catch (OperationCanceledException)
{
diff --git a/src/ServiceControl.AcceptanceTesting/Sequence.cs b/src/ServiceControl.AcceptanceTesting/Sequence.cs
index f4599815e4..37c366fea6 100644
--- a/src/ServiceControl.AcceptanceTesting/Sequence.cs
+++ b/src/ServiceControl.AcceptanceTesting/Sequence.cs
@@ -18,7 +18,7 @@ public Sequence Do(string step, Func handler)
{
steps.Add(async context =>
{
- await handler(context).ConfigureAwait(false);
+ await handler(context);
return true;
});
stepNames.Add(step);
@@ -39,7 +39,7 @@ public async Task Continue(TContext context)
}
var step = steps[currentStep];
- var advance = await step(context).ConfigureAwait(false);
+ var advance = await step(context);
if (advance)
{
var nextStep = currentStep + 1;
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs b/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
new file mode 100644
index 0000000000..c0ec329d4b
--- /dev/null
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/AcceptanceTestStorageConfiguration.cs
@@ -0,0 +1,50 @@
+namespace ServiceControl.AcceptanceTests
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net.NetworkInformation;
+ using System.Threading.Tasks;
+ using Persistence.RavenDb;
+
+ class AcceptanceTestStorageConfiguration
+ {
+ public string PersistenceType { get; protected set; }
+
+ public Task> CustomizeSettings()
+ {
+ return Task.FromResult>(new Dictionary
+ {
+ { "RavenDB35/RunInMemory", bool.TrueString},
+ { "DatabaseMaintenancePort", FindAvailablePort(33334).ToString()},
+ { "HostName", "localhost" }
+ });
+ }
+
+ public Task Configure()
+ {
+ PersistenceType = typeof(RavenDbPersistenceConfiguration).AssemblyQualifiedName;
+
+ return Task.CompletedTask;
+ }
+
+ static int FindAvailablePort(int startPort)
+ {
+ var activeTcpListeners = IPGlobalProperties
+ .GetIPGlobalProperties()
+ .GetActiveTcpListeners();
+
+ for (var port = startPort; port < startPort + 1024; port++)
+ {
+ var portCopy = port;
+ if (activeTcpListeners.All(endPoint => endPoint.Port != portCopy))
+ {
+ return port;
+ }
+ }
+
+ return startPort;
+ }
+
+ public Task Cleanup() => Task.CompletedTask;
+ }
+}
diff --git a/src/ServiceControl.AcceptanceTests/App.config b/src/ServiceControl.AcceptanceTests.RavenDB/App.config
similarity index 100%
rename from src/ServiceControl.AcceptanceTests/App.config
rename to src/ServiceControl.AcceptanceTests.RavenDB/App.config
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/Legacy/AuditRetention.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Legacy/AuditRetention.cs
new file mode 100644
index 0000000000..84979bf317
--- /dev/null
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Legacy/AuditRetention.cs
@@ -0,0 +1,114 @@
+namespace ServiceControl.MultiInstance.AcceptanceTests.SagaAudit
+{
+ using System;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using AcceptanceTesting;
+ using EventLog;
+ using Microsoft.Extensions.DependencyInjection;
+ using NServiceBus;
+ using NServiceBus.AcceptanceTesting;
+ using NServiceBus.CustomChecks;
+ using NUnit.Framework;
+ using Raven.Client;
+ using ServiceBus.Management.Infrastructure.Settings;
+ using ServiceControl.AcceptanceTests;
+ using ServiceControl.AcceptanceTests.TestSupport.EndpointTemplates;
+ using ServiceControl.Persistence;
+ using ServiceControl.Persistence.RavenDb.SagaAudit;
+ using ServiceControl.SagaAudit;
+
+
+ class AuditRetention : AcceptanceTest
+ {
+ [Test]
+ public async Task
+ Check_fails_if_no_audit_retention_is_configured()
+ {
+ ////Ensure custom checks are enabled
+ SetSettings = settings =>
+ {
+ settings.DisableHealthChecks = false;
+ settings.AuditRetentionPeriod = TimeSpan.FromSeconds(5);
+ };
+
+ //Override the configuration of the check in the container in order to make it run more frequently for testing purposes.
+ CustomizeHostBuilder = hostBuilder => hostBuilder.ConfigureServices((ctx, services) =>
+ services.AddTransient(provider => new AuditRetentionCustomCheck(provider.GetRequiredService(), provider.GetRequiredService(), TimeSpan.FromSeconds(10))));
+
+ SingleResult customCheckEventEntry = default;
+ bool sagaAudiDataInMainInstanceIsAvailableForQuery = false;
+
+ await Define()
+ .WithEndpoint(b => b.When((bus, c) => bus.SendLocal(new MessageInitiatingSaga { Id = "Id" })))
+ .Done(async c =>
+ {
+ if (!c.SagaId.HasValue)
+ {
+ return false;
+ }
+
+ if (sagaAudiDataInMainInstanceIsAvailableForQuery == false)
+ {
+ var sagaData =
+ await this.TryGet($"/api/sagas/{c.SagaId}");
+ sagaAudiDataInMainInstanceIsAvailableForQuery = sagaData.HasResult;
+ return false;
+ }
+
+ customCheckEventEntry = await this.TryGetSingle("/api/eventlogitems/",
+ e => e.EventType == "CustomCheckFailed" && e.Description.StartsWith("Saga Audit Data Retention"));
+
+ return customCheckEventEntry;
+ })
+ .Run();
+
+ Assert.IsTrue(customCheckEventEntry.Item.RelatedTo.Any(item => item == "/customcheck/Saga Audit Data Retention"), "Event log entry should be related to the Saga Audit Data Retention");
+ Assert.IsTrue(customCheckEventEntry.Item.RelatedTo.Any(item => item.StartsWith("/endpoint/Particular.ServiceControl")), "Event log entry should be related to the ServiceControl endpoint");
+ }
+
+ public class SagaEndpoint : EndpointConfigurationBuilder
+ {
+ public SagaEndpoint()
+ {
+ EndpointSetup(c =>
+ {
+ c.AuditSagaStateChanges(Settings.DEFAULT_SERVICE_NAME);
+ });
+ }
+
+ public class MySaga : Saga, IAmStartedByMessages
+ {
+ public MyContext TestContext { get; set; }
+
+ public Task Handle(MessageInitiatingSaga message, IMessageHandlerContext context)
+ {
+ TestContext.SagaId = Data.Id;
+ return Task.CompletedTask;
+ }
+
+ protected override void ConfigureHowToFindSaga(SagaPropertyMapper mapper)
+ {
+ mapper.ConfigureMapping(msg => msg.Id).ToSaga(saga => saga.MessageId);
+ }
+ }
+
+ public class MySagaData : ContainSagaData
+ {
+ public string MessageId { get; set; }
+ }
+ }
+
+
+ public class MessageInitiatingSaga : ICommand
+ {
+ public string Id { get; set; }
+ }
+
+
+ public class MyContext : ScenarioContext
+ {
+ public Guid? SagaId { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ServiceControl.AcceptanceTests/Legacy/When_processed_message_is_still_available.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Legacy/When_processed_message_is_still_available.cs
similarity index 80%
rename from src/ServiceControl.AcceptanceTests/Legacy/When_processed_message_is_still_available.cs
rename to src/ServiceControl.AcceptanceTests.RavenDB/Legacy/When_processed_message_is_still_available.cs
index 709810ab15..51db54d943 100644
--- a/src/ServiceControl.AcceptanceTests/Legacy/When_processed_message_is_still_available.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Legacy/When_processed_message_is_still_available.cs
@@ -1,4 +1,4 @@
-namespace ServiceControl.AcceptanceTests.Legacy
+namespace ServiceControl.AcceptanceTests.RavenDB.Legacy
{
using System;
using System.Collections.Generic;
@@ -8,9 +8,9 @@
using AcceptanceTesting;
using AcceptanceTests;
using CompositeViews.Messages;
- using Infrastructure.RavenDB;
using MessageAuditing;
using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Hosting;
using NServiceBus;
using NServiceBus.AcceptanceTesting;
using NUnit.Framework;
@@ -28,7 +28,7 @@ public async Task Should_be_accessible_via_the_rest_api()
CustomizeHostBuilder = hostBuilder
=> hostBuilder.ConfigureServices((hostBuilderContext, services)
- => services.AddSingleton(new CreateMessageDataMigration(messageId)));
+ => services.AddHostedService(sp => new CreateMessageDataMigration(messageId, sp.GetRequiredService())));
MessagesView auditedMessage = null;
byte[] body = null;
@@ -58,13 +58,18 @@ public async Task Should_be_accessible_via_the_rest_api()
Assert.AreEqual("Some Content", bodyAsString);
}
- class CreateMessageDataMigration : IDataMigration
+ class CreateMessageDataMigration : IHostedService
{
readonly string messageId;
+ readonly IDocumentStore store;
- public CreateMessageDataMigration(string messageId) => this.messageId = messageId;
+ public CreateMessageDataMigration(string messageId, IDocumentStore store)
+ {
+ this.messageId = messageId;
+ this.store = store;
+ }
- public async Task Migrate(IDocumentStore store)
+ public async Task StartAsync(CancellationToken cancellationToken)
{
using (var documentSession = store.OpenAsyncSession())
{
@@ -84,13 +89,14 @@ public async Task Migrate(IDocumentStore store)
ProcessedAt = DateTime.UtcNow
};
- await documentSession.StoreAsync(processedMessage);
- await documentSession.SaveChangesAsync();
+ await documentSession.StoreAsync(processedMessage, cancellationToken);
+ await documentSession.SaveChangesAsync(cancellationToken);
}
SpinWait.SpinUntil(() => store.DatabaseCommands.GetStatistics().StaleIndexes.Length == 0, TimeSpan.FromSeconds(10));
-
}
+
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
public class Endpoint : EndpointConfigurationBuilder
diff --git a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/FailedErrorsController.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/FailedErrorsController.cs
similarity index 95%
rename from src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/FailedErrorsController.cs
rename to src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/FailedErrorsController.cs
index 4885e33c32..d266f8d60b 100644
--- a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/FailedErrorsController.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/FailedErrorsController.cs
@@ -1,4 +1,4 @@
-namespace ServiceControl.AcceptanceTests.Recoverability.MessageFailures
+namespace ServiceControl.AcceptanceTests.RavenDB.Recoverability.MessageFailures
{
using System;
using System.Net;
@@ -6,11 +6,11 @@
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
+ using Infrastructure.RavenDB.Expiration;
using Infrastructure.WebApi;
using Operations;
using Raven.Client;
using Raven.Client.Embedded;
- using Infrastructure.RavenDB.Expiration;
public class FailedErrorsCountReponse
{
@@ -40,7 +40,7 @@ public async Task GetFailedErrorsCount()
{
Count = count
})
- .WithEtag(stats);
+ .WithEtag(stats.IndexEtag);
}
}
diff --git a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/FailedMessageRetriesController.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/FailedMessageRetriesController.cs
similarity index 85%
rename from src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/FailedMessageRetriesController.cs
rename to src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/FailedMessageRetriesController.cs
index 9b149f5dd1..e2ac53e9b2 100644
--- a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/FailedMessageRetriesController.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/FailedMessageRetriesController.cs
@@ -1,4 +1,4 @@
-namespace ServiceControl.AcceptanceTests.Recoverability.MessageFailures
+namespace ServiceControl.AcceptanceTests.RavenDB.Recoverability.MessageFailures
{
using System.Net;
using System.Net.Http;
@@ -26,13 +26,13 @@ public async Task GetFailedMessageRetriesCount()
{
using (var session = store.OpenAsyncSession())
{
- await session.Query().Statistics(out var stats).ToListAsync().ConfigureAwait(false);
+ await session.Query().Statistics(out var stats).ToListAsync();
return Request.CreateResponse(HttpStatusCode.OK, new FailedMessageRetriesCountReponse
{
Count = stats.TotalResults
})
- .WithEtag(stats);
+ .WithEtag(stats.IndexEtag);
}
}
diff --git a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
similarity index 96%
rename from src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
rename to src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
index 7a52dad9d2..5a7a9415d5 100644
--- a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_failed_message_is_retried.cs
@@ -1,4 +1,4 @@
-namespace ServiceControl.AcceptanceTests.Recoverability.MessageFailures
+namespace ServiceControl.AcceptanceTests.RavenDB.Recoverability.MessageFailures
{
using System;
using System.Collections.Generic;
@@ -6,6 +6,7 @@
using System.Threading.Tasks;
using AcceptanceTesting;
using Infrastructure;
+ using Microsoft.Extensions.DependencyInjection;
using NServiceBus;
using NServiceBus.AcceptanceTesting;
using NServiceBus.Features;
@@ -18,6 +19,15 @@
class When_a_failed_message_is_retried : AcceptanceTest
{
+ public When_a_failed_message_is_retried()
+ {
+ CustomizeHostBuilder = builder => builder.ConfigureServices((hostContext, services) =>
+ {
+ services.AddScoped();
+ services.AddScoped();
+ });
+ }
+
[Test]
public async Task Should_remove_failedmessageretries_when_retrying_groups()
{
diff --git a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/When_a_message_fails_to_import.cs b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
similarity index 95%
rename from src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
rename to src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
index e6bfc688f2..180e9f2813 100644
--- a/src/ServiceControl.AcceptanceTests/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/Recoverability/MessageFailures/When_a_message_fails_to_import.cs
@@ -1,4 +1,4 @@
-namespace ServiceControl.AcceptanceTests.Recoverability.MessageFailures
+namespace ServiceControl.AcceptanceTests.RavenDB.Recoverability.MessageFailures
{
using System;
using System.Threading.Tasks;
@@ -6,6 +6,8 @@
using Contracts.MessageFailures;
using Infrastructure;
using Infrastructure.DomainEvents;
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Hosting;
using NServiceBus;
using NServiceBus.AcceptanceTesting;
using NServiceBus.AcceptanceTesting.Customization;
@@ -40,6 +42,8 @@ public async Task It_can_be_reimported()
settings.ErrorLogQueue = Conventions.EndpointNamingConvention(typeof(ErrorLogSpy));
};
+ CustomizeHostBuilder = builder => builder.ConfigureServices(services => services.AddScoped());
+
var runResult = await Define()
.WithEndpoint(b => b.When((bus, c) => bus.Send(new MyMessage())))
.WithEndpoint(b => b.DoNotFailOnErrorMessages())
diff --git a/src/ServiceControl.AcceptanceTests/ServiceControl.AcceptanceTests.csproj b/src/ServiceControl.AcceptanceTests.RavenDB/ServiceControl.AcceptanceTests.RavenDB.csproj
similarity index 83%
rename from src/ServiceControl.AcceptanceTests/ServiceControl.AcceptanceTests.csproj
rename to src/ServiceControl.AcceptanceTests.RavenDB/ServiceControl.AcceptanceTests.RavenDB.csproj
index 48f2fd6b08..be29578e9e 100644
--- a/src/ServiceControl.AcceptanceTests/ServiceControl.AcceptanceTests.csproj
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/ServiceControl.AcceptanceTests.RavenDB.csproj
@@ -7,12 +7,10 @@
-
-
-
+
@@ -20,10 +18,14 @@
-
+
-
\ No newline at end of file
+
+
+
+
+
diff --git a/src/ServiceControl.AcceptanceTests/ServiceControl.runsettings b/src/ServiceControl.AcceptanceTests.RavenDB/ServiceControl.runsettings
similarity index 100%
rename from src/ServiceControl.AcceptanceTests/ServiceControl.runsettings
rename to src/ServiceControl.AcceptanceTests.RavenDB/ServiceControl.runsettings
diff --git a/src/ServiceControl.AcceptanceTests.RavenDB/TestsFilter.cs b/src/ServiceControl.AcceptanceTests.RavenDB/TestsFilter.cs
new file mode 100644
index 0000000000..b207ccee13
--- /dev/null
+++ b/src/ServiceControl.AcceptanceTests.RavenDB/TestsFilter.cs
@@ -0,0 +1,2 @@
+// This project alone tends to take ~13 minutes on GitHub Actions runner
+[assembly: IncludeInTestCategory("Raven35Acceptance")]
\ No newline at end of file
diff --git a/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_critical_storage_threshold_reached.cs b/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_critical_storage_threshold_reached.cs
index 5f718cfaf4..77c357fb30 100644
--- a/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_critical_storage_threshold_reached.cs
+++ b/src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_critical_storage_threshold_reached.cs
@@ -2,32 +2,53 @@
{
using System;
using System.Linq;
+ using System.Threading;
using System.Threading.Tasks;
using AcceptanceTesting;
using MessageFailures.Api;
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Hosting;
using NServiceBus;
using NServiceBus.AcceptanceTesting;
using NUnit.Framework;
+ using Persistence;
using ServiceBus.Management.Infrastructure.Settings;
using TestSupport.EndpointTemplates;
[TestFixture]
class When_critical_storage_threshold_reached : AcceptanceTest
{
-
[SetUp]
- public void SetupIngestion() =>
+ public void SetupIngestion()
+ {
SetSettings = s =>
{
s.TimeToRestartErrorIngestionAfterFailure = TimeSpan.FromSeconds(1);
s.DisableHealthChecks = false;
- s.MinimumStorageLeftRequiredForIngestion = 0;
};
+ }
+ class PersisterSettingsRetriever : IHostedService
+ {
+ static PersistenceSettings _persistenceSettings;
+
+ public PersisterSettingsRetriever(PersistenceSettings persistenceSettings, int value)
+ {
+ _persistenceSettings = persistenceSettings;
+ SetMinimumStorageLeftForIngestion(value);
+ }
+
+ public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+
+ public static void SetMinimumStorageLeftForIngestion(int value) => _persistenceSettings.PersisterSpecificSettings["MinimumStorageLeftRequiredForIngestion"] = value.ToString();
+ }
[Test]
public async Task Should_stop_ingestion()
{
+ CustomizeHostBuilder = hostBuilder => hostBuilder.ConfigureServices(services => services.AddHostedService(b => new PersisterSettingsRetriever(b.GetRequiredService(), 0)));
+
await Define()
.WithEndpoint(b => b
.When(context =>
@@ -35,7 +56,7 @@ await Define()
return context.Logs.ToArray().Any(i => i.Message.StartsWith("Ensure started. Infrastructure started"));
}, (_, __) =>
{
- Settings.MinimumStorageLeftRequiredForIngestion = 100;
+ PersisterSettingsRetriever.SetMinimumStorageLeftForIngestion(100);
return Task.CompletedTask;
})
.When(context =>
@@ -46,13 +67,14 @@ await Define()
}, (bus, c) => bus.SendLocal(new MyMessage())
)
.DoNotFailOnErrorMessages())
- .Done(async c => await this.TryGetSingle("/api/errors") == false)
+ //.Done(async c => await this.TryGetSingle("/api/errors") == false)
.Run();
}
[Test]
public async Task Should_stop_ingestion_and_resume_when_more_space_is_available()
{
+ CustomizeHostBuilder = hostBuilder => hostBuilder.ConfigureServices(services => services.AddHostedService(b => new PersisterSettingsRetriever(b.GetRequiredService(), 0)));
var ingestionShutdown = false;
await Define()
@@ -64,7 +86,7 @@ await Define()
"Ensure started. Infrastructure started"));
}, (session, context) =>
{
- Settings.MinimumStorageLeftRequiredForIngestion = 100;
+ PersisterSettingsRetriever.SetMinimumStorageLeftForIngestion(100);
return Task.CompletedTask;
})
.When(context =>
@@ -81,7 +103,7 @@ await Define()
})
.When(c => ingestionShutdown, (session, context) =>
{
- Settings.MinimumStorageLeftRequiredForIngestion = 0;
+ PersisterSettingsRetriever.SetMinimumStorageLeftForIngestion(0);
return Task.CompletedTask;
})
.DoNotFailOnErrorMessages())
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 c5d027e83e..2b673fc322 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
@@ -1,18 +1,20 @@
namespace ServiceControl.AcceptanceTests.Monitoring.CustomChecks
{
- using System;
- using System.IO;
- using System.Linq;
- using System.Threading.Tasks;
- using Infrastructure.RavenDB;
using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Hosting;
using Notifications;
using NServiceBus;
using NServiceBus.AcceptanceTesting;
using NServiceBus.CustomChecks;
using NUnit.Framework;
- using Raven.Client;
using ServiceBus.Management.Infrastructure.Settings;
+ using ServiceControl.Persistence;
+ using ServiceControl.Persistence.RavenDb.Editing;
+ using System;
+ using System.IO;
+ using System.Linq;
+ using System.Threading;
+ using System.Threading.Tasks;
using TestSupport.EndpointTemplates;
[TestFixture]
@@ -32,8 +34,7 @@ public async Task Should_send_custom_check_status_change_emails()
};
CustomizeHostBuilder = hostBuilder =>
- hostBuilder.ConfigureServices((hostBuilderContext, services) =>
- services.AddSingleton());
+ hostBuilder.ConfigureServices(services => services.AddHostedService());
await Define(c =>
{
@@ -58,31 +59,31 @@ await Define(c =>
Assert.AreEqual("Subject: [Particular.ServiceControl] health check failed", emailText[6]);
}
- class CreateNotificationsDataMigration : IDataMigration
+ class SetupNotificationSettings : IHostedService
{
- public Task Migrate(IDocumentStore store)
+ IErrorMessageDataStore errorMessageDataStore;
+
+ public SetupNotificationSettings(IErrorMessageDataStore errorMessageDataStore)
{
- using (var session = store.OpenSession())
- {
- var notificationsSettings = new NotificationsSettings
- {
- Id = NotificationsSettings.SingleDocumentId,
- Email = new EmailNotifications
- {
- Enabled = true,
- From = "YouServiceControl@particular.net",
- To = "WhoeverMightBeConcerned@particular.net",
- }
- };
-
- session.Store(notificationsSettings);
-
- session.SaveChanges();
- }
+ this.errorMessageDataStore = errorMessageDataStore;
+ }
- return Task.CompletedTask;
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ var notificationsManager = await errorMessageDataStore.CreateNotificationsManager();
+
+ var settings = await notificationsManager.LoadSettings();
+ settings.Email = new EmailNotifications
+ {
+ Enabled = true,
+ From = "YouServiceControl@particular.net",
+ To = "WhoeverMightBeConcerned@particular.net",
+ };
+ await notificationsManager.SaveChanges();
}
+
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
public class MyContext : ScenarioContext
diff --git a/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs b/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs
index 0e6ee741bb..4c97cd1571 100644
--- a/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs
+++ b/src/ServiceControl.AcceptanceTests/Monitoring/InternalCustomChecks/When_a_critical_error_is_triggered.cs
@@ -1,48 +1,42 @@
namespace ServiceControl.AcceptanceTests.Monitoring.InternalCustomChecks
{
using System;
- using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AcceptanceTesting;
using Contracts.CustomChecks;
using EventLog;
+ using Microsoft.Extensions.DependencyInjection;
using NServiceBus.AcceptanceTesting;
- using NServiceBus.CustomChecks;
using NUnit.Framework;
- using Operations;
- using ServiceControl.CustomChecks;
+ using ServiceControl.Operations;
[TestFixture]
-
class When_a_critical_error_is_triggered : AcceptanceTest
{
- static Type[] allServiceControlTypes = typeof(InternalCustomChecks).Assembly.GetTypes();
- static IEnumerable allTypesExcludingBuiltInCustomChecks = allServiceControlTypes.Where(t => !t.GetInterfaces().Contains(typeof(ICustomCheck)));
- static Type[] customChecksUnderTest = { typeof(CriticalErrorCustomCheck) };
- static IEnumerable typesToScan = allTypesExcludingBuiltInCustomChecks.Concat(customChecksUnderTest);
-
[Test]
public async Task Service_control_is_not_killed_and_error_is_reported_via_custom_check()
{
+ CustomizeHostBuilder = builder => builder.ConfigureServices((hostContext, services) =>
+ {
+ services.AddScoped();
+ services.AddTransient(_ => new CriticalErrorCustomCheck(TimeSpan.FromSeconds(1))); // Overrides existing registration to have an increased test interval
+ });
+
SetSettings = settings =>
{
settings.DisableHealthChecks = false;
};
EventLogItem entry = null;
- var criticalErrorTriggered = false;
-
await Define()
.Done(async c =>
{
- if (!criticalErrorTriggered)
- {
- await this.Post