Skip to content

Commit

Permalink
Making sure that message with a pre-existing sagaId won't start new s…
Browse files Browse the repository at this point in the history
…aga.

Fixes #2446
Adding failing acpt test for #2446

Making sure that a messages with a sagaid header won't start new sagas

Since they are targeted to a specific saga a new one should not be created
if it can't be found.

Fixes #2446

Adding test to verify that saga type should match

So that other sagas could be started

Conflicts:
	src/NServiceBus.Core/Sagas/SagaPersistenceBehavior.cs
  • Loading branch information
John Simons committed Oct 8, 2014
1 parent 5e66316 commit 978e847
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 4 deletions.
Expand Up @@ -172,6 +172,7 @@
<Compile Include="Sagas\Issue_2044.cs" />
<Compile Include="Sagas\When_doing_request_response_between_sagas.cs" />
<Compile Include="Sagas\Issue_1819.cs" />
<Compile Include="Sagas\When_message_has_a_saga_id.cs" />
<Compile Include="Sagas\When_sending_from_a_saga_timeout.cs" />
<Compile Include="Sagas\When_sending_from_a_saga_handle.cs" />
<Compile Include="Sagas\When_an_endpoint_replies_to_a_saga.cs" />
Expand Down
@@ -0,0 +1,95 @@
namespace NServiceBus.AcceptanceTests.Sagas
{
using System;
using NServiceBus.AcceptanceTesting;
using NServiceBus.AcceptanceTests.EndpointTemplates;
using NServiceBus.Saga;
using NUnit.Framework;

public class When_message_has_a_saga_id : NServiceBusAcceptanceTest
{
[Test]
public void Should_not_start_a_new_saga_if_not_found()
{
var context = Scenario.Define<Context>()
.WithEndpoint<SagaEndpoint>(b => b.Given(bus =>
{
var message = new MessageWithSagaId();
bus.SetMessageHeader(message, Headers.SagaId, Guid.NewGuid().ToString());
bus.SetMessageHeader(message, Headers.SagaType, typeof(MySaga).AssemblyQualifiedName);
bus.SendLocal(message);
}))
.Done(c => c.NotFoundHandlerCalled && c.OtherSagaStarted)
.Run(TimeSpan.FromSeconds(15));

Assert.True(context.NotFoundHandlerCalled);
Assert.True(context.OtherSagaStarted);
Assert.False(context.MessageHandlerCalled);
Assert.False(context.TimeoutHandlerCalled);
}

class MySaga : Saga<MySaga.SagaData>, IAmStartedByMessages<MessageWithSagaId>,
IHandleTimeouts<MessageWithSagaId>,
IHandleSagaNotFound
{
public Context Context { get; set; }

public class SagaData : ContainSagaData
{
}

public void Handle(MessageWithSagaId message)
{
Context.MessageHandlerCalled = true;
}

public void Handle(object message)
{
Context.NotFoundHandlerCalled = true;
}

public void Timeout(MessageWithSagaId state)
{
Context.TimeoutHandlerCalled = true;
}
}

class MyOtherSaga : Saga<MyOtherSaga.SagaData>, IAmStartedByMessages<MessageWithSagaId>
{
public Context Context { get; set; }

public void Handle(MessageWithSagaId message)
{
Context.OtherSagaStarted = true;
}

public class SagaData : ContainSagaData
{
}

}


class Context : ScenarioContext
{
public bool NotFoundHandlerCalled { get; set; }
public bool MessageHandlerCalled { get; set; }
public bool TimeoutHandlerCalled { get; set; }
public bool OtherSagaStarted { get; set; }
}

public class SagaEndpoint : EndpointConfigurationBuilder
{
public SagaEndpoint()
{
EndpointSetup<DefaultServer>();
}
}

public class MessageWithSagaId : IMessage
{
}
}
}
Expand Up @@ -85,5 +85,4 @@ public class Saga1Timeout : IMessage
{
}
}

}
23 changes: 20 additions & 3 deletions src/NServiceBus.Core/Sagas/SagaPersistenceBehavior.cs
Expand Up @@ -44,7 +44,7 @@ public void Invoke(HandlerInvocationContext context, Action next)
if (loadedEntity == null)
{
//if this message are not allowed to start the saga
if (!Features.Sagas.ShouldMessageStartSaga(sagaInstanceState.SagaType, context.LogicalMessage.MessageType))
if (!IsAllowedToStartANewSaga(context, sagaInstanceState))
{
sagaInstanceState.MarkAsNotFound();

Expand All @@ -59,13 +59,11 @@ public void Invoke(HandlerInvocationContext context, Action next)
sagaInstanceState.AttachExistingEntity(loadedEntity);
}


if (IsTimeoutMessage(context.LogicalMessage))
{
context.MessageHandler.Invocation = HandlerInvocationCache.InvokeTimeout;
}


next();

if (sagaInstanceState.NotFound)
Expand Down Expand Up @@ -100,6 +98,25 @@ public void Invoke(HandlerInvocationContext context, Action next)
}
}

bool IsAllowedToStartANewSaga(HandlerInvocationContext context, ActiveSagaInstance sagaInstanceState)
{
string sagaType;

if (context.LogicalMessage.Headers.ContainsKey(Headers.SagaId) &&
context.LogicalMessage.Headers.TryGetValue(Headers.SagaType, out sagaType))
{
//we want to move away from the assembly fully qualified name since that will break if you move sagas
// between assemblies. We use the fullname instead which is enough to identify the saga
if (sagaType.StartsWith(sagaInstanceState.SagaType.FullName))
{
//so now we have a saga id for this saga and if we can't find it we shouldn't start a new one
return false;
}
}

return Features.Sagas.ShouldMessageStartSaga(sagaInstanceState.SagaType, context.LogicalMessage.MessageType);
}

void InvokeSagaNotFoundHandlers()
{
logger.InfoFormat("Could not find a saga for the message type {0}. Going to invoke SagaNotFoundHandlers.", currentContext.LogicalMessage.MessageType.FullName);
Expand Down

0 comments on commit 978e847

Please sign in to comment.