Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to pre-create Saga instances #62

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/MySystem.AcceptanceTests/When_requesting_a_timeout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public async Task It_should_be_rescheduled_and_handled()
.Done(ctx => ctx.MessageWasProcessedBySaga<ASaga.MyTimeout, ASaga>() || ctx.HasFailedMessages())
.Run();

Assert.True(context.MessageWasProcessedBySaga<ASaga.MyTimeout, ASaga>());
Assert.False(context.HasFailedMessages());
Assert.False(context.HasHandlingErrors());
Assert.False(context.HasFailedMessages(), "There are failed messages");
Assert.False(context.HasHandlingErrors(), "There were handling errors");
Assert.True(context.MessageWasProcessedBySaga<ASaga.MyTimeout, ASaga>(), "MyTimeout was not processed by ASaga");
}

class MyServiceEndpoint : EndpointConfigurationBuilder
Expand Down
4 changes: 2 additions & 2 deletions src/MySystem.AcceptanceTests/When_sending_AMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ public async Task AReplyMessage_is_received_and_ASaga_is_started()

var invokedSaga = context.InvokedSagas.Single(s => s.SagaType == typeof(ASaga));

Assert.False(context.HasFailedMessages(), "There are failed messages");
Assert.False(context.HasHandlingErrors(), "There were handling errors");
Assert.True(invokedSaga.IsNew);
Assert.AreEqual("MyService", invokedSaga.EndpointName);
Assert.True(((ASagaData)invokedSaga.SagaData).AnIdentifier == theExpectedIdentifier);
Assert.False(context.HasFailedMessages());
Assert.False(context.HasHandlingErrors());
}

class MyServiceEndpoint : EndpointConfigurationBuilder
Expand Down
6 changes: 3 additions & 3 deletions src/MySystem.AcceptanceTests/When_sending_CompleteASaga.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public async Task ASaga_is_completed()
behavior.When(condition: ctx =>
{
return ctx.SagaWasInvoked<ASaga>() && ctx.InvokedSagas.Any(s=> s.SagaType == typeof(ASaga) && s.IsNew);
},
},
action: session =>
{
return session.Send("MyService", new CompleteASaga {AnIdentifier = theExpectedIdentifier});
Expand All @@ -54,10 +54,10 @@ public async Task ASaga_is_completed()
var newSaga = invokedSagas.SingleOrDefault(s => s.IsNew);
var completedSaga = invokedSagas.SingleOrDefault(s => s.IsCompleted);

Assert.False(context.HasFailedMessages(), "There are failed messages");
Assert.False(context.HasHandlingErrors(), "There were handling errors");
Assert.IsNotNull(newSaga);
Assert.IsNotNull(completedSaga);
Assert.False(context.HasFailedMessages());
Assert.False(context.HasHandlingErrors());
}

class MyServiceEndpoint : EndpointConfigurationBuilder
Expand Down
13 changes: 10 additions & 3 deletions src/NServiceBus.IntegrationTesting/EndpointTemplate.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using NServiceBus.AcceptanceTesting.Support;
using NServiceBus.Configuration.AdvancedExtensibility;
using NServiceBus.IntegrationTesting.Messages.Handlers;
using System;
using System.Threading.Tasks;
using NServiceBus.AcceptanceTesting.Customization;

namespace NServiceBus.IntegrationTesting
{
Expand All @@ -13,11 +15,16 @@ public async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescr

var settings = configuration.GetSettings();
endpointCustomizationConfiguration.EndpointName = settings.EndpointName();
configurationBuilderCustomization(configuration);

configuration.RegisterRequiredPipelineBehaviors(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext);
configuration.RegisterScenarioContext(runDescriptor.ScenarioContext);
configuration.TypesToIncludeInScan(new[]
{
typeof(CreateSagaInstanceHandler),
typeof(MarkSagaInstanceAsCreatedHandler)
});

configurationBuilderCustomization(configuration);
configuration.RegisterScenarioContext(runDescriptor.ScenarioContext);
configuration.RegisterRequiredPipelineBehaviors(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext);

return configuration;
}
Expand Down
11 changes: 11 additions & 0 deletions src/NServiceBus.IntegrationTesting/IntegrationScenarioContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class IntegrationScenarioContext : ScenarioContext
readonly ConcurrentBag<SagaInvocation> invokedSagas = new ConcurrentBag<SagaInvocation>();
readonly ConcurrentBag<OutgoingMessageOperation> outgoingMessageOperations = new ConcurrentBag<OutgoingMessageOperation>();
readonly Dictionary<Type, Func<object, DoNotDeliverBefore, DoNotDeliverBefore>> timeoutRescheduleRules = new Dictionary<Type, Func<object, DoNotDeliverBefore, DoNotDeliverBefore>>();
readonly ConcurrentDictionary<Guid, Type> createdSagaInstances = new ConcurrentDictionary<Guid, Type>();

public IEnumerable<HandlerInvocation> InvokedHandlers { get { return invokedHandlers; } }
public IEnumerable<SagaInvocation> InvokedSagas { get { return invokedSagas; } }
Expand Down Expand Up @@ -53,6 +54,16 @@ internal SagaInvocation CaptureInvokedSaga(SagaInvocation invocation)
return invocation;
}

internal void RegisterSagaInstanceAsCreated(Guid sagaId, Type sagaDataType)
{
createdSagaInstances.AddOrUpdate(sagaId, sagaDataType, (id, type) => type);
}

public bool IsSagaInstanceAvailable(Guid sagaId)
{
return createdSagaInstances.ContainsKey(sagaId);
}

public bool HandlerWasInvoked<THandler>()
{
return InvokedHandlers.Any(invocation => invocation.HandlerType == typeof(THandler));
Expand Down
20 changes: 20 additions & 0 deletions src/NServiceBus.IntegrationTesting/MessageSessionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Threading.Tasks;

namespace NServiceBus.IntegrationTesting
{
public static class MessageSessionExtensions
{
public static Task CreateSagaInstance<TSagaData>(this IMessageSession messageSession, string sagaOwnerEndpoint, Guid sagaId, TSagaData sagaData, string originator = null, string originatingMessageId = null) where TSagaData : IContainSagaData
{
sagaData.Id = sagaId;
sagaData.Originator = originator;
sagaData.OriginalMessageId = originatingMessageId;

return messageSession.Send(sagaOwnerEndpoint, new Messages.CreateSagaInstance()
{
SagaData = sagaData
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace NServiceBus.IntegrationTesting.Messages
{
class CreateSagaInstance
{
public string CorrelationPropertyName { get; set; }
public object CorrelationPropertyValue { get; set; }
public IContainSagaData SagaData { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using NServiceBus.AcceptanceTesting;
using NServiceBus.Sagas;
using System.Threading.Tasks;

namespace NServiceBus.IntegrationTesting.Messages.Handlers
{
class CreateSagaInstanceHandler : IHandleMessages<CreateSagaInstance>
{
readonly ISagaPersister sagaPersister;

public CreateSagaInstanceHandler(ISagaPersister sagaPersister)
{
this.sagaPersister = sagaPersister;
}

public async Task Handle(CreateSagaInstance message, IMessageHandlerContext context)
{
var correlationProperty = new SagaCorrelationProperty(
message.CorrelationPropertyName,
message.CorrelationPropertyValue);

await sagaPersister.Save(message.SagaData,
correlationProperty,
context.SynchronizedStorageSession,
new Extensibility.ContextBag())
.ConfigureAwait(false);

await context.SendLocal(new MarkSagaInstanceAsCreated()
{
SagaId = message.SagaData.Id,
SagaDataType = message.SagaData.GetType()
}).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace NServiceBus.IntegrationTesting.Messages.Handlers
{
class MarkSagaInstanceAsCreatedHandler : IHandleMessages<MarkSagaInstanceAsCreated>
{
readonly IntegrationScenarioContext integrationScenarioContext;

public MarkSagaInstanceAsCreatedHandler(IntegrationScenarioContext integrationScenarioContext)
{
this.integrationScenarioContext = integrationScenarioContext;
}

public Task Handle(MarkSagaInstanceAsCreated message, IMessageHandlerContext context)
{
integrationScenarioContext.RegisterSagaInstanceAsCreated(message.SagaId, message.SagaDataType);

return Task.CompletedTask;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace NServiceBus.IntegrationTesting.Messages
{
class MarkSagaInstanceAsCreated
{
public Guid SagaId { get; set; }
public Type SagaDataType { get; set; }
}
}