public CommandContext( string entityId, long sequence, string commandName, long commandId, AnySupport anySupport, IEventSourcedEntityHandler eventSourcedEntityHandler, int snapshotEvery, AbstractContext abstractContext, AbstractClientActionContext abstractClientActionContext, AbstractEffectContext abstractEffectContext, IActivatableContext activatableContext) { EntityId = entityId; Sequence = sequence; CommandName = commandName; CommandId = commandId; AnySupport = anySupport; EventSourcedEntityHandler = eventSourcedEntityHandler; SnapshotEvery = snapshotEvery; AbstractContext = abstractContext; AbstractClientActionContext = abstractClientActionContext; AbstractEffectContext = abstractEffectContext; ActivatableContext = activatableContext; }
private async Task HandleCommand(IEventSourcedStatefulService statefulService, MessageStreamingContext <EventSourcedStreamIn, EventSourcedStreamOut> stream, EventSourcedStreamIn message, string entityId, long sequence, IEventSourcedEntityHandler eventSourcedEntityHandler) { var command = message.Command; if (command.EntityId != entityId) { throw new InvalidOperationException("Entity received a message was not intended for itself"); } var activatableContext = new AbstractActivatableContext(); var commandContext = new CommandContext( entityId, sequence, command.Name, command.Id, statefulService.AnySupport, eventSourcedEntityHandler, statefulService.SnapshotEvery, new AbstractContext(RootContext), new AbstractClientActionContext(command.Id, RootContext, activatableContext), new AbstractEffectContext(activatableContext), activatableContext ); var reply = Optional.Option.None <Any>(); try { // FIXME is this allowed to throw reply = eventSourcedEntityHandler.HandleCommand(command.Payload, commandContext); } catch (Exception ex) { switch (ex) { case FailInvokedException _: reply = Optional.Option.Some(Any.Pack(new Empty())); break; } } finally { activatableContext.Deactivate(); } var anyResult = reply.ValueOr(() => throw new InvalidOperationException("Command result was null")); var clientAction = commandContext.AbstractClientActionContext.CreateClientAction(reply, false); EventSourcedReply outReply; if (!commandContext.AbstractClientActionContext.HasError) { var endSequenceNumber = sequence + commandContext.Events.Count; var snapshot = Optional.Option.None <Any>(); if (commandContext.PerformSnapshot) { var s = eventSourcedEntityHandler.Snapshot( new SnapshotContext( entityId, endSequenceNumber, RootContext.ServiceCallFactory ) ); if (s.HasValue) { snapshot = s; } } outReply = new EventSourcedReply { CommandId = message.Command.Id, ClientAction = clientAction.ValueOr(() => throw new ArgumentNullException(nameof(clientAction))) }; outReply.SideEffects.Add(commandContext.AbstractEffectContext.SideEffects); outReply.Events.Add(commandContext.Events); // UNSAFE snapshot.MatchSome(x => outReply.Snapshot = x); } else { outReply = new EventSourcedReply { CommandId = message.Command.Id, ClientAction = new ClientAction { Reply = new Reply { Payload = anyResult } } }; } await stream.Response.WriteAsync( new EventSourcedStreamOut { Reply = outReply } ); }