Exemple #1
0
 public static IEnumerable <T> SelectResults <T>(this FutureConsumeContext context)
     where T : class
 {
     return(context.Instance.HasResults()
         ? context.Instance.Results.Where(x => x.Value.HasMessageType <T>()).Select(x => x.Value.ToObject <T>())
         : Enumerable.Empty <T>());
 }
Exemple #2
0
        public async Task Execute(FutureConsumeContext <TInput> context)
        {
            var factory = context.GetStateMachineActivityFactory();

            IItineraryPlanner <TInput> itineraryPlanner = factory.GetService <IItineraryPlanner <TInput> >(context);

            var trackingNumber = NewId.NextGuid();

            var builder = new RoutingSlipBuilder(trackingNumber);

            builder.AddVariable(nameof(FutureConsumeContext.FutureId), context.FutureId);

            builder.AddSubscription(context.ReceiveContext.InputAddress, RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);

            await itineraryPlanner.PlanItinerary(context, builder).ConfigureAwait(false);

            var routingSlip = builder.Build();

            await context.Execute(routingSlip).ConfigureAwait(false);

            if (TrackRoutingSlip)
            {
                context.Instance.Pending.Add(trackingNumber);
            }
        }
Exemple #3
0
        public static void SetFault <TFault>(this FutureConsumeContext context, Guid id, TFault fault, DateTime?timestamp = default)
            where TFault : class
        {
            SetFaulted(context, id, timestamp);

            context.Instance.Faults[id] = new FutureMessage <TFault>(fault);
        }
        public Task SetFaulted(BehaviorContext <FutureState, TInput> context)
        {
            FutureConsumeContext <TInput> consumeContext = context.CreateFutureConsumeContext();

            return(consumeContext.Instance.HasSubscriptions()
                ? _endpoint.SendFault(consumeContext, consumeContext.Instance.Subscriptions.ToArray())
                : _endpoint.SendFault(consumeContext));
        }
Exemple #5
0
        public async Task SendFault(FutureConsumeContext <TResult> context, params FutureSubscription[] subscriptions)
        {
            var fault = await _factory(context).ConfigureAwait(false);

            context.SetFault(context.Instance.CorrelationId, fault);

            await context.SendMessageToSubscriptions(subscriptions, fault).ConfigureAwait(false);
        }
 static object MapOrderBurger(FutureConsumeContext <Burger> context)
 {
     return(new
     {
         OrderId = context.Instance.CorrelationId,
         OrderLineId = context.Message.BurgerId,
         Burger = context.Message
     });
 }
Exemple #7
0
        public static void AddSubscription(this FutureConsumeContext context)
        {
            if (context.ResponseAddress == null)
            {
                return;
            }

            context.Instance.Subscriptions.Add(new FutureSubscription(context.ResponseAddress, context.RequestId));
        }
 static object MapOrderBurger <TPatty, TCondiments>(FutureConsumeContext <Burger <TPatty, TCondiments> > context) where TCondiments : Condiments
 {
     return(new
     {
         OrderId = context.Instance.CorrelationId,
         OrderLineId = context.Message.BurgerId,
         Burger = context.Message
     });
 }
Exemple #9
0
        public static async Task <TValue> SetVariable <TValue>(this FutureConsumeContext context, string key, AsyncFutureMessageFactory <TValue> factory)
            where TValue : class
        {
            var value = await factory(context).ConfigureAwait(false);

            context.Instance.Variables[key] = value;

            return(value);
        }
 static object MapOrderFry(FutureConsumeContext <Fry> context)
 {
     return(new
     {
         OrderId = context.Instance.CorrelationId,
         OrderLineId = context.Message.FryId,
         context.Message.Size,
     });
 }
Exemple #11
0
        public static TValue SetVariable <TValue>(this FutureConsumeContext context, string key, FutureMessageFactory <TValue> factory)
            where TValue : class
        {
            var value = factory(context);

            context.Instance.Variables[key] = value;

            return(value);
        }
 static object MapOrderShake(FutureConsumeContext <Shake> context)
 {
     return(new
     {
         OrderId = context.Instance.CorrelationId,
         OrderLineId = context.Message.ShakeId,
         context.Message.Size,
         context.Message.Flavor
     });
 }
        /// <summary>
        /// Use when a request is received after the initial request is still awaiting completion
        /// </summary>
        /// <param name="binder"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static EventActivityBinder <FutureState, T> AddSubscription <T>(this EventActivityBinder <FutureState, T> binder)
            where T : class
        {
            return(binder.Then(context =>
            {
                FutureConsumeContext <T> consumeContext = context.CreateFutureConsumeContext(context.Data);

                consumeContext.AddSubscription();
            }));
        }
Exemple #14
0
        public static void SetResult <TResult>(this FutureConsumeContext context, Guid id, TResult result)
            where TResult : class
        {
            if (!context.Instance.Completed.HasValue)
            {
                SetCompleted(context, id);
            }

            context.Instance.Results[id] = new FutureMessage <TResult>(result);
        }
Exemple #15
0
        public static void SetFault <T, TFault>(this FutureConsumeContext <T> context, Guid id, FutureMessageFactory <T, TFault> factory)
            where T : class
            where TFault : class
        {
            SetFaulted(context, id);

            var result = factory(context);

            context.Instance.Faults[id] = new FutureMessage <TFault>(result);
        }
        static object MapOrderFaulted(FutureConsumeContext context)
        {
            Dictionary <Guid, Fault> faults = context.Instance.Faults.ToDictionary(x => x.Key, x => x.Value.ToObject <Fault>());

            return(new
            {
                LinesCompleted = context.Instance.Results.ToDictionary(x => x.Key, x => x.Value.ToObject <OrderLineCompleted>()),
                LinesFaulted = faults,
                Exceptions = faults.SelectMany(x => x.Value.Exceptions).ToArray()
            });
        }
Exemple #17
0
        public static bool TryGetVariable <T>(this FutureConsumeContext future, string key, out T result)
            where T : class
        {
            if (future.Instance.HasVariables())
            {
                return(future.Instance.Variables.TryGetValue(key, out result));
            }

            result = default;
            return(false);
        }
Exemple #18
0
        public static EventActivityBinder <FutureState, TData> SetVariable <TData, TValue>(this EventActivityBinder <FutureState, TData> binder, string key,
                                                                                           AsyncFutureMessageFactory <TData, TValue> valueFactory)
            where TData : class
            where TValue : class
        {
            return(binder.Add(new AsyncActivity <FutureState, TData>(context =>
            {
                FutureConsumeContext <TData> futureContext = context.CreateFutureConsumeContext(context.Data);

                return futureContext.SetVariable(key, valueFactory);
            })));
        }
        /// <summary>
        /// Set the result associated with the identifier using the message factory
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="messageFactory">Should return the result message</param>
        /// <typeparam name="TResult">The result type</typeparam>
        /// <returns></returns>
        public static EventActivityBinder <FutureState, RoutingSlipFaulted> SetFault <TResult>(this EventActivityBinder <FutureState, RoutingSlipFaulted> binder,
                                                                                               FutureMessageFactory <RoutingSlipFaulted, TResult> messageFactory)
            where TResult : class
        {
            return(binder.Then(context =>
            {
                FutureConsumeContext <RoutingSlipFaulted> consumeContext = context.CreateFutureConsumeContext();

                var resultId = consumeContext.Message.TrackingNumber;

                consumeContext.SetFault(resultId, messageFactory);
            }));
        }
Exemple #20
0
        public static void SetResult <T, TResult>(this FutureConsumeContext <T> context, Guid id, FutureMessageFactory <T, TResult> factory)
            where T : class
            where TResult : class
        {
            if (!context.Instance.Completed.HasValue)
            {
                SetCompleted(context, id);
            }

            var result = factory(context);

            context.Instance.Results[id] = new FutureMessage <TResult>(result);
        }
Exemple #21
0
        public static void SetFaulted(this FutureConsumeContext context, Guid id, DateTime?timestamp = default)
        {
            timestamp ??= context.SentTime ?? DateTime.UtcNow;

            var future = context.Instance;

            if (future.HasPending())
            {
                future.Pending?.Remove(id);
            }

            future.Faulted ??= timestamp;
        }
Exemple #22
0
        public static async Task <TResult> SetResult <TResult>(this FutureConsumeContext context, Guid id, AsyncFutureMessageFactory <TResult> factory)
            where TResult : class
        {
            if (!context.Instance.Completed.HasValue)
            {
                SetCompleted(context, id);
            }

            var result = await factory(context).ConfigureAwait(false);

            context.Instance.Results[id] = new FutureMessage <TResult>(result);

            return(result);
        }
        /// <summary>
        /// Set the result associated with the identifier using the message factory
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="getResultId">Should return the result identifier</param>
        /// <param name="messageFactory">Should return the result message</param>
        /// <typeparam name="T">The event type</typeparam>
        /// <typeparam name="TResult">The result type</typeparam>
        /// <returns></returns>
        public static EventActivityBinder <FutureState, T> SetResult <T, TResult>(this EventActivityBinder <FutureState, T> binder,
                                                                                  Func <FutureConsumeContext <T>, Guid> getResultId, FutureMessageFactory <T, TResult> messageFactory)
            where T : class
            where TResult : class
        {
            return(binder.Then(context =>
            {
                FutureConsumeContext <T> consumeContext = context.CreateFutureConsumeContext();

                var resultId = getResultId(consumeContext);

                consumeContext.SetResult(resultId, messageFactory);
            }));
        }
        /// <summary>
        /// Initialize the FutureState properties of the request
        /// </summary>
        /// <param name="binder"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static EventActivityBinder <FutureState, T> InitializeFuture <T>(this EventActivityBinder <FutureState, T> binder)
            where T : class
        {
            return(binder
                   .Then(context =>
            {
                FutureConsumeContext <T> consumeContext = context.CreateFutureConsumeContext(context.Data);

                context.Instance.Created = DateTime.UtcNow;
                context.Instance.Command = new FutureMessage <T>(consumeContext.Message);
                context.Instance.Location = new FutureLocation(context.Instance.CorrelationId, consumeContext.ReceiveContext.InputAddress);

                consumeContext.AddSubscription();
            }));
        }
Exemple #25
0
        static object RoutingSlipFaultedValueProvider(FutureConsumeContext <RoutingSlipFaulted> context)
        {
            var message = context.Instance.GetCommand <TCommand>();

            IEnumerable <ExceptionInfo> exceptions = context.Message.ActivityExceptions.Select(x => x.ExceptionInfo);

            return(new
            {
                FaultId = context.MessageId ?? NewId.NextGuid(),
                FaultedMessageId = context.Message.TrackingNumber,
                FaultMessageTypes = TypeMetadataCache <TCommand> .MessageTypeNames,
                Host = context.Message.ActivityExceptions.Select(x => x.Host).FirstOrDefault() ?? context.Host,
                context.Message.Timestamp,
                exceptions,
                message
            });
        }
        async Task Execute(FutureConsumeContext <T> consumeContext)
        {
            // this will need to be done by a consumer at some point, to handle retry/fault handling

            var trackingNumber = NewId.NextGuid();

            var builder = new RoutingSlipBuilder(trackingNumber);

            builder.AddVariable(nameof(consumeContext.FutureId), consumeContext.FutureId);

            builder.AddSubscription(consumeContext.ReceiveContext.InputAddress, RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);

            await _planner.PlanItinerary(consumeContext.Message, builder).ConfigureAwait(false);

            var routingSlip = builder.Build();

            await consumeContext.Execute(routingSlip).ConfigureAwait(false);
        }
Exemple #27
0
        public async Task PlanItinerary(FutureConsumeContext <OrderBurger> context, ItineraryBuilder builder)
        {
            var orderBurger = context.Message;

            builder.AddVariable(nameof(OrderBurger.OrderId), orderBurger.OrderId);
            builder.AddVariable(nameof(OrderBurger.OrderLineId), orderBurger.OrderLineId);

            var burger = orderBurger.Burger;

            builder.AddActivity(nameof(GrillBurgerActivity), _grillAddress, new
            {
                burger.Weight,
                burger.Cheese,
            });

            Guid?onionRingId = default;

            if (burger.OnionRing)
            {
                onionRingId = NewId.NextGuid();

                // TODO create a future with address/id
                await context.Publish <OrderOnionRings>(new
                {
                    orderBurger.OrderId,
                    OrderLineId = onionRingId,
                    Quantity    = 1
                });
            }

            builder.AddActivity(nameof(DressBurgerActivity), _dressAddress, new
            {
                burger.Lettuce,
                burger.Pickle,
                burger.Onion,
                burger.Ketchup,
                burger.Mustard,
                burger.BarbecueSauce,
                burger.OnionRing,
                onionRingId
            });
        }
Exemple #28
0
        public static void SetCompleted(this FutureConsumeContext context, Guid id)
        {
            var timestamp = context.SentTime ?? DateTime.UtcNow;

            var future = context.Instance;

            if (future.HasPending())
            {
                future.Pending.Remove(id);

                if (!future.HasPending() && !future.HasFaults())
                {
                    future.Completed = timestamp;
                }
            }
            else if (!future.HasFaults())
            {
                future.Completed = timestamp;
            }
        }
Exemple #29
0
        public async Task SendResponse(FutureConsumeContext <TResponse> context, params FutureSubscription[] subscriptions)
        {
            context.SetCompleted(context.Instance.CorrelationId);

            InitializeContext <TResult> initializeContext = await MessageInitializerCache <TResult> .Initialize(new
            {
                context.Instance.Completed,
                context.Instance.Created,
                context.Instance.Faulted,
                context.Instance.Location,
            }, context.CancellationToken);

            var request = context.Instance.GetCommand <TCommand>();

            if (request != null)
            {
                initializeContext = await MessageInitializerCache <TResult> .Initialize(initializeContext, request);
            }

            if (context.Message != null)
            {
                initializeContext = await MessageInitializerCache <TResult> .Initialize(initializeContext, context.Message);
            }

            // this is due to the way headers are propagated via the initializer
            var values = _provider(context);

            IMessageInitializer <TResult> initializer = MessageInitializerCache <TResult> .GetInitializer(values.GetType());

            var result = await context.SendMessageToSubscriptions(subscriptions, initializer, initializeContext, values).ConfigureAwait(false);

            if (result == null)
            {
                // initialize the message and save it as the response
                InitializeContext <TResult> messageContext = await initializer.Initialize(initializeContext, values).ConfigureAwait(false);

                result = messageContext.Message;
            }

            context.SetResult(context.Instance.CorrelationId, result);
        }
Exemple #30
0
        public async Task Execute(FutureConsumeContext <TInput> context)
        {
            var trackingNumber = NewId.NextGuid();

            var builder = new RoutingSlipBuilder(trackingNumber);

            builder.AddVariable(nameof(FutureConsumeContext.FutureId), context.FutureId);

            builder.AddSubscription(context.ReceiveContext.InputAddress, RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);

            await _buildItinerary(context, builder).ConfigureAwait(false);

            var routingSlip = builder.Build();

            await context.Execute(routingSlip).ConfigureAwait(false);

            if (TrackRoutingSlip)
            {
                context.Instance.Pending.Add(trackingNumber);
            }
        }