private static MessageContext processMessageInCore
            (TriggerMessageContext context)
        {
            // get the handler for the message
            var serviceCommand
                = context
                  .MessageContext
                  .ServiceContext
                  .ServiceCommandFactory[context.MessageContext.Message.MessageType];

            var serviceRequest
                = new ServiceRequest(
                      dataModel: context.MessageContext.ServiceContext.ServiceDataModel
                      , message: context.MessageContext.Message.Body
                      );

            var serviceResponse
                = serviceCommand.Handle(serviceRequest);

            // todo: move this to a factory method ( note fix outcomType todo first )
            var outcomeContext
                = new MessageContext(
                      serviceContext: context.MessageContext.ServiceContext
                      , message: new Message(
                          requestId: context.MessageContext.Message.RequestId
                          , messageId: context.OutomceMessageId
                          , messageType: $"{serviceCommand.GetType().Name}Result"
                          , message: ServiceResponseJsonConverter.Serialise(serviceResponse)
                          )
                      );

            return(outcomeContext);
        }
        private static MessageContext processMessage
            (TriggerMessageContext triggerContext)
        {
            if (triggerContext == null)
            {
                throw new ArgumentNullException(nameof(triggerContext));
            }


            var transaction
                = triggerContext
                  .MessageContext
                  .ServiceContext
                  .ServiceDataModel
                  .Database
                  .BeginTransaction(IsolationLevel.Serializable);

            try {
                var outcome
                    = triggerContext
                      .fmap(recordMessageInMessageStore)
                      .fmap(processMessageInCore)
                      .fmap(recordMessageOutcome)
                    ;

                triggerContext
                .MessageContext
                .ServiceContext
                .ServiceDataModel
                .SaveChanges();

                transaction.Commit();

                return(outcome);
            } finally {
                transaction.Dispose(); // will roll back the transaction if needed
            }
        }
        private static TriggerMessageContext recordMessageInMessageStore
            (TriggerMessageContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }


            context
            .MessageContext
            .ServiceContext
            .ServiceDataModel
            .WriteMessage(context.MessageContext.Message, context.OutomceMessageId);


            context
            .MessageContext
            .ServiceContext
            .ServiceDataModel
            .SaveChanges();

            return(context);
        }