Skip to content

Commit

Permalink
Chinchilla-Software-Com#13 Updated the tests to properly show how to …
Browse files Browse the repository at this point in the history
…create a proper event handler that locates the correct saga.

Chinchilla-Software-Com#14 Correctly use the right resolver in the correct way.
  • Loading branch information
greyoy committed Jun 13, 2017
1 parent 1edc83c commit b972fb0
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 17 deletions.
Expand Up @@ -20,31 +20,36 @@ public class ConversationReportProcessManagerEventHandlers
/// <summary>
/// Instantiates the <see cref="ConversationReportProcessManagerEventHandlers"/> class registering any <see cref="ReceiveActor.Receive{T}(System.Func{T,System.Threading.Tasks.Task})"/> required.
/// </summary>
public ConversationReportProcessManagerEventHandlers(IAkkaAggregateResolver aggregateResolver)
public ConversationReportProcessManagerEventHandlers(IAkkaSagaResolver sagaResolver)
{
AggregateResolver = aggregateResolver;
SagaResolver = sagaResolver;
}

protected IAkkaAggregateResolver AggregateResolver { get; private set; }
protected IAkkaSagaResolver SagaResolver { get; private set; }

#region Implementation of IMessageHandler<in HelloWorldRepliedTo>

public void Handle(HelloWorldRepliedTo message)
protected virtual void HandleEvent(IEvent<Guid> message)
{
IActorRef item = AggregateResolver.ResolveActor<ConversationReportProcessManager>();
// Resolve and locate the instance of the Saga to pass the message to
IActorRef item = SagaResolver.ResolveActor<ConversationReportProcessManager, Guid>(message.Id);
// Pass the message to it (and wait?)
bool result = item.Ask<bool>(message).Result;
// item.Tell(message);
}

public void Handle(HelloWorldRepliedTo message)
{
HandleEvent(message);
}

#endregion

#region Implementation of IMessageHandler<in HelloWorldSaid>

public void Handle(HelloWorldSaid message)
{
IActorRef item = AggregateResolver.ResolveActor<ConversationReportProcessManager>();
bool result = item.Ask<bool>(message).Result;
// item.Tell(message);
HandleEvent(message);
}

#endregion
Expand All @@ -53,9 +58,7 @@ public void Handle(HelloWorldSaid message)

public void Handle(ConversationEnded message)
{
IActorRef item = AggregateResolver.ResolveActor<ConversationReportProcessManager>();
bool result = item.Ask<bool>(message).Result;
// item.Tell(message);
HandleEvent(message);
}

#endregion
Expand Down
60 changes: 58 additions & 2 deletions Framework/Cqrs.Tests/Substitutes/TestSaga.cs
Expand Up @@ -7,11 +7,67 @@

namespace Cqrs.Tests.Substitutes
{
public class TestSaga
: Saga<ISingleSignOnToken>
public class TestSagaEventHandlers
: SagaEventHandler<ISingleSignOnToken, TestSaga>
, IEventHandler<ISingleSignOnToken, TestAggregateDidSomething>
, IEventHandler<ISingleSignOnToken, TestAggregateDidSomethingElse>
, IEventHandler<ISingleSignOnToken, TestAggregateDidSomethingElse2>
{
public TestSagaEventHandlers(IDependencyResolver dependencyResolver, ILogger logger, ISagaUnitOfWork<ISingleSignOnToken> sagaUnitOfWork) : base(dependencyResolver, logger, sagaUnitOfWork)
{
}

/// <summary>
/// A constructor for the <see cref="Cqrs.Domain.Factories.IAggregateFactory"/>
/// </summary>
public TestSagaEventHandlers(IDependencyResolver dependencyResolver, ILogger logger) : base(dependencyResolver, logger)
{
}

#region Implementation of IMessageHandler<in TestAggregateDidSomething>

public void Handle(TestAggregateDidSomething message)
{
// There are two ways for this to pan out.
// 1) Events WILL arrive in order in which case this handler would ADD TO and all others would GET FROM the UOW
// 2) Events may not arrive in order in which case all handlers should try to GET FROM and if it fails ADD TO the UOW
// Given this is a test, we'll code for the first.

var saga = new TestSaga(DependencyResolver, message.Id == Guid.Empty ? Guid.NewGuid() : message.Id);
saga.Handle(message);
SagaUnitOfWork.Add(saga);
SagaUnitOfWork.Commit();
}

#endregion

#region Implementation of IMessageHandler<in TestAggregateDidSomethingElse>

public void Handle(TestAggregateDidSomethingElse message)
{
TestSaga saga = GetSaga(message.Id);
saga.Handle(message);
SagaUnitOfWork.Add(saga);
SagaUnitOfWork.Commit();
}

#endregion

#region Implementation of IMessageHandler<in TestAggregateDidSomethingElse2>

public void Handle(TestAggregateDidSomethingElse2 message)
{
TestSaga saga = GetSaga(message.Id);
saga.Handle(message);
SagaUnitOfWork.Add(saga);
SagaUnitOfWork.Commit();
}

#endregion
}

public class TestSaga : Saga<ISingleSignOnToken>

{
public int DidSomethingCount;

Expand Down
1 change: 1 addition & 0 deletions Framework/Cqrs/Cqrs.csproj
Expand Up @@ -134,6 +134,7 @@
<Compile Include="Domain\Repository.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Domain\SagaEventHandler.cs" />
<Compile Include="Domain\SagaRepository.cs" />
<Compile Include="Domain\SagaDescriptor.cs" />
<Compile Include="Domain\AggregateDescriptor.cs" />
Expand Down
44 changes: 44 additions & 0 deletions Framework/Cqrs/Domain/SagaEventHandler.cs
@@ -0,0 +1,44 @@
#region Copyright
// // -----------------------------------------------------------------------
// // <copyright company="cdmdotnet Limited">
// // Copyright cdmdotnet Limited. All rights reserved.
// // </copyright>
// // -----------------------------------------------------------------------
#endregion

using System;
using cdmdotnet.Logging;
using Cqrs.Configuration;

namespace Cqrs.Domain
{
public abstract class SagaEventHandler<TAuthenticationToken, TSaga>
where TSaga : ISaga<TAuthenticationToken>
{
protected ISagaUnitOfWork<TAuthenticationToken> SagaUnitOfWork { get; private set; }

protected IDependencyResolver DependencyResolver { get; private set; }

protected ILogger Logger { get; private set; }

/// <summary>
/// A constructor for the <see cref="Cqrs.Domain.Factories.IAggregateFactory"/>
/// </summary>
protected SagaEventHandler(IDependencyResolver dependencyResolver, ILogger logger)
: this(dependencyResolver, logger, dependencyResolver.Resolve<ISagaUnitOfWork<TAuthenticationToken>>())
{
}

protected SagaEventHandler(IDependencyResolver dependencyResolver, ILogger logger, ISagaUnitOfWork<TAuthenticationToken> sagaUnitOfWork)
{
DependencyResolver = dependencyResolver;
Logger = logger;
SagaUnitOfWork = sagaUnitOfWork;
}

protected virtual TSaga GetSaga(Guid id)
{
return SagaUnitOfWork.Get<TSaga>(id);
}
}
}
Expand Up @@ -15,6 +15,7 @@ namespace Cqrs.Ninject.Akka
public class AkkaNinjectDependencyResolver
: NinjectDependencyResolver
, IAkkaAggregateResolver
, IAkkaSagaResolver
, IHandlerResolver
{
protected global::Akka.DI.Ninject.NinjectDependencyResolver RawAkkaNinjectDependencyResolver { get; set; }
Expand Down Expand Up @@ -107,6 +108,21 @@ public IActorRef ResolveActor<T>()

#endregion

#region Implementation of IAkkaSagaResolver

IActorRef IAkkaSagaResolver.ResolveActor<TSaga, TAuthenticationToken>(Guid rsn)
{
return ResolveSagaActor<TSaga, TAuthenticationToken>(rsn);
}

public virtual IActorRef ResolveSagaActor<TSaga, TAuthenticationToken>(Guid rsn)
where TSaga : ISaga<TAuthenticationToken>
{
return (IActorRef)AkkaResolve(typeof(TSaga), rsn, true);
}

#endregion

protected virtual object RootResolve(Type serviceType)
{
return base.Resolve(serviceType);
Expand Down
16 changes: 12 additions & 4 deletions Sample/CQRSWeb/IoC.cs
Expand Up @@ -25,6 +25,7 @@ public static class IoC {
x.For<IAuthenticationTokenHelper<ISingleSignOnToken>>().Singleton().Use<AuthenticationTokenHelper>();
x.For<InProcessBus<ISingleSignOnToken>>().Singleton().Use<InProcessBus<ISingleSignOnToken>>();
x.For<IAggregateFactory>().Singleton().Use<AggregateFactory>();
x.For<ICommandPublisher<ISingleSignOnToken>>().Use(y => y.GetInstance<InProcessBus<ISingleSignOnToken>>());
x.For<ICommandSender<ISingleSignOnToken>>().Use(y => y.GetInstance<InProcessBus<ISingleSignOnToken>>());
x.For<IEventPublisher<ISingleSignOnToken>>().Use(y => y.GetInstance<InProcessBus<ISingleSignOnToken>>());
x.For<IHandlerRegistrar>().Use(y => y.GetInstance<InProcessBus<ISingleSignOnToken>>());
Expand All @@ -37,10 +38,17 @@ public static class IoC {
x.For<ICommandHandlerRegistrar>().Singleton().Use<InProcessBus<ISingleSignOnToken>>();
x.For<IEventHandlerRegistrar>().Singleton().Use<InProcessBus<ISingleSignOnToken>>();
x.For<IRepository<ISingleSignOnToken>>().HybridHttpOrThreadLocalScoped().Use(y =>
new CacheRepository<ISingleSignOnToken>(
new Repository<ISingleSignOnToken>(y.GetInstance<IAggregateFactory>(), y.GetInstance<IEventStore<ISingleSignOnToken>>(), y.GetInstance<IEventPublisher<ISingleSignOnToken>>(), y.GetInstance<ICorrelationIdHelper>()),
y.GetInstance<IEventStore<ISingleSignOnToken>>()));
x.For<IAggregateRepository<ISingleSignOnToken>>()
.HybridHttpOrThreadLocalScoped()
.Use
(
y =>
new CacheRepository<ISingleSignOnToken>
(
new AggregateRepository<ISingleSignOnToken>(y.GetInstance<IAggregateFactory>(), y.GetInstance<IEventStore<ISingleSignOnToken>>(), y.GetInstance<IEventPublisher<ISingleSignOnToken>>(), y.GetInstance<ICorrelationIdHelper>()),
y.GetInstance<IEventStore<ISingleSignOnToken>>()
)
);
// Scan the assembly the ReadModelFacade class is in and then configure using the pattern
// IClass == Class
Expand Down

0 comments on commit b972fb0

Please sign in to comment.