Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using Akka.Actor;
12 : using cdmdotnet.Logging;
13 : using Cqrs.Akka.Domain;
14 : using Cqrs.Authentication;
15 : using Cqrs.Commands;
16 : using Cqrs.Configuration;
17 :
18 : namespace Cqrs.Akka.Commands
19 : {
20 : /// <summary>
21 : /// A <see cref="ICommandPublisher{TAuthenticationToken}"/> that proxies <see cref="ICommand{TAuthenticationToken}"/> to the <see cref="IActorRef"/> which acts as a single point of all handler resolutions.
22 : /// </summary>
23 : /// <typeparam name="TAuthenticationToken">The <see cref="Type"/> of the authentication token.</typeparam>
24 : public class AkkaCommandBusProxy<TAuthenticationToken>
25 : : IAkkaCommandPublisherProxy<TAuthenticationToken>
26 1 : {
27 : /// <summary>
28 : /// Instantiates a new instance of <see cref="AkkaCommandBusProxy{TAuthenticationToken}"/>.
29 : /// </summary>
30 1 : public AkkaCommandBusProxy(IDependencyResolver dependencyResolver, ICorrelationIdHelper correlationIdHelper, IAuthenticationTokenHelper<TAuthenticationToken> authenticationTokenHelper)
31 : {
32 : CorrelationIdHelper = correlationIdHelper;
33 : AuthenticationTokenHelper = authenticationTokenHelper;
34 : CommandHandlerResolver = ((IAkkaAggregateResolver)dependencyResolver).ResolveActor<BusActor>();
35 : }
36 :
37 : /// <summary>
38 : /// Gets the <see cref="IActorRef">command handler resolver</see> that we send/proxy the command to.
39 : /// </summary>
40 : protected IActorRef CommandHandlerResolver { get; private set; }
41 :
42 : /// <summary>
43 : /// Gets or sets the <see cref="ICorrelationIdHelper"/>.
44 : /// </summary>
45 : protected ICorrelationIdHelper CorrelationIdHelper { get; private set; }
46 :
47 : /// <summary>
48 : /// Gets or sets the <see cref="IAuthenticationTokenHelper{TAuthenticationToken}">Authentication Token Helper</see>.
49 : /// </summary>
50 : protected IAuthenticationTokenHelper<TAuthenticationToken> AuthenticationTokenHelper { get; private set; }
51 :
52 : #region Implementation of ICommandSender<TAuthenticationToken>
53 :
54 : /// <summary>
55 : /// Publishes the provided <paramref name="command"/> on the command bus.
56 : /// </summary>
57 1 : public virtual void Publish<TCommand>(TCommand command)
58 : where TCommand : ICommand<TAuthenticationToken>
59 : {
60 : // We only set these two properties as they are not going to be available across the thread/task
61 : if (command.AuthenticationToken == null || command.AuthenticationToken.Equals(default(TAuthenticationToken)))
62 : command.AuthenticationToken = AuthenticationTokenHelper.GetAuthenticationToken();
63 : command.CorrelationId = CorrelationIdHelper.GetCorrelationId();
64 :
65 : bool result = CommandHandlerResolver.Ask<bool>(command).Result;
66 : }
67 :
68 : /// <summary>
69 : /// Publishes the provided <paramref name="commands"/> on the command bus.
70 : /// </summary>
71 1 : public virtual void Publish<TCommand>(IEnumerable<TCommand> commands)
72 : where TCommand : ICommand<TAuthenticationToken>
73 : {
74 : foreach (TCommand rawCommand in commands)
75 : {
76 : // Lambda scoping thing
77 : TCommand command = rawCommand;
78 : // We only set these two properties as they are not going to be available across the thread/task
79 : if (command.AuthenticationToken == null || command.AuthenticationToken.Equals(default(TAuthenticationToken)))
80 : command.AuthenticationToken = AuthenticationTokenHelper.GetAuthenticationToken();
81 : command.CorrelationId = CorrelationIdHelper.GetCorrelationId();
82 :
83 : bool result = CommandHandlerResolver.Ask<bool>(command).Result;
84 : }
85 : }
86 :
87 : #endregion
88 :
89 : /// <summary>
90 : /// Similar to a <see cref="ICommandPublisher{TAuthenticationToken}"/>, passes commands onto the <see cref="CommandHandlerResolver"/>.
91 : /// </summary>
92 : public class BusActor
93 : : ReceiveActor
94 1 : {
95 : /// <summary>
96 : /// Instantiates a new instance of <see cref="BusActor"/>.
97 : /// </summary>
98 1 : public BusActor(IAkkaCommandPublisher<TAuthenticationToken> commandHandlerResolver, ICorrelationIdHelper correlationIdHelper, IAuthenticationTokenHelper<TAuthenticationToken> authenticationTokenHelper)
99 : {
100 : CommandHandlerResolver = commandHandlerResolver;
101 : CorrelationIdHelper = correlationIdHelper;
102 : AuthenticationTokenHelper = authenticationTokenHelper;
103 : Receive<ICommand<TAuthenticationToken>>(command => ExecuteReceive(command));
104 : }
105 :
106 : /// <summary>
107 : /// Gets or sets the <see cref="IAkkaCommandPublisher{TAuthenticationToken}"/>.
108 : /// </summary>
109 : protected IAkkaCommandPublisher<TAuthenticationToken> CommandHandlerResolver { get; private set; }
110 :
111 : /// <summary>
112 : /// Gets or sets the <see cref="ICorrelationIdHelper"/>.
113 : /// </summary>
114 : protected ICorrelationIdHelper CorrelationIdHelper { get; private set; }
115 :
116 : /// <summary>
117 : /// Gets or sets the <see cref="IAuthenticationTokenHelper{TAuthenticationToken}"/>.
118 : /// </summary>
119 : protected IAuthenticationTokenHelper<TAuthenticationToken> AuthenticationTokenHelper { get; private set; }
120 :
121 : /// <summary>
122 : /// Passes the provided <paramref name="command"/> to <see cref="CommandHandlerResolver"/> via <see cref="ICommandPublisher{TAuthenticationToken}.Publish{TCommand}(TCommand)"/>
123 : /// then calls <see cref="ActorRefImplicitSenderExtensions.Tell"/>.
124 : /// </summary>
125 1 : protected virtual void ExecuteReceive(ICommand<TAuthenticationToken> command)
126 : {
127 : try
128 : {
129 : AuthenticationTokenHelper.SetAuthenticationToken(command.AuthenticationToken);
130 : CorrelationIdHelper.SetCorrelationId(command.CorrelationId);
131 : CommandHandlerResolver.Publish(command);
132 :
133 : Sender.Tell(true);
134 : }
135 : catch
136 : {
137 : Sender.Tell(false);
138 : throw;
139 : }
140 : }
141 : }
142 : }
143 : }
|