A structure that represents a decision task. Decision tasks are sent to deciders in order for them to make decisions.

Inheritance: Amazon.Runtime.AmazonWebServiceResponse
        /// <summary>
        /// Constructor for the workflow event processor. 
        /// </summary>
        /// <param name="decisionTask">Decision task passed in from SWF as decision task response.</param>
        /// <param name="workflows">IEnumerable set of string for workflow name and Type for workflow class.</param>
        /// <param name="request">The request used to retrieve <paramref name="decisionTask"/>, which will be used to retrieve subsequent history event pages.</param>
        /// <param name="swfClient">An SWF client.</param>
        public WorkflowEventsProcessor(DecisionTask decisionTask, IEnumerable<KeyValuePair<string, Type>> workflows, PollForDecisionTaskRequest request, IAmazonSimpleWorkflow swfClient)
        {
            // Decision task can't be null.
            if (decisionTask == null)
            {
                throw new ArgumentNullException("decisionTask");
            }

            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            // Store the decision task and allocate a new decision context and event dictionary which
            // we will use as we walk through the chain of events
            _decisionTask = decisionTask;
            _request = request;
            _decisionContext = new WorkflowDecisionContext();
            _swfClient = swfClient;

            // Set up our events data structure
            _events = new WorkflowEventsIterator(ref decisionTask, _request, _swfClient);
            _workflows = (Dictionary<string, Type>) workflows;
        }
Exemplo n.º 2
0
        public override List<Decision> Decide(DecisionTask task)
        {
            var decisions = new List<Decision>();
            List<ActivityState> activityStates;
            string startingInput;
            //ProcessHistory(task, out startingInput, out activityStates);

            HistoryIterator iterator = new HistoryIterator(this.Client, task);
            foreach (var evnt in iterator)
            {
                if (evnt.EventType == EventType.WorkflowExecutionStarted)
                {
                    //startingInput = evnt.WorkflowExecutionStartedEventAttributes.Input;  //this.Deserialize<WorkFlowExecutionInput>(evnt.WorkflowExecutionStartedEventAttributes.Input);

                    decisions.Add(new Decision()
                    {
                        DecisionType = DecisionType.ScheduleActivityTask,
                        ScheduleActivityTaskDecisionAttributes = new ScheduleActivityTaskDecisionAttributes()
                        {
                            ActivityType = new ActivityType()
                            {
                                Name = Constants.ActivityName,
                                Version = Constants.ActivityVersion
                            },
                            ActivityId = Constants.ActivityIdPrefix + DateTime.Now.TimeOfDay,
                            Input = evnt.WorkflowExecutionStartedEventAttributes.Input  
                        }

                    });

                }
                if (evnt.EventType == EventType.ActivityTaskCompleted)
                {
                    //ActivityState state = this.Deserialize<ActivityState>(evnt.ActivityTaskCompletedEventAttributes.Result);
                    //activityStates.Add(state);

                    decisions.Add(new Decision()
                    {
                        DecisionType = DecisionType.CompleteWorkflowExecution,
                        CompleteWorkflowExecutionDecisionAttributes = new CompleteWorkflowExecutionDecisionAttributes
                        {
                            Result = "We are done"
                        }
                    });
                }
            }


            

            //if (decisions.Count == 0)
            //{
            //    decisions.Add(new Decision()
            //    {
            //        DecisionType = DecisionType.CompleteWorkflowExecution,
            //        CompleteWorkflowExecutionDecisionAttributes = new CompleteWorkflowExecutionDecisionAttributes
            //        {
            //            Result = "We are done"
            //        }
            //    });
            //}

            return decisions;
        }
Exemplo n.º 3
0
        void ProcessHistory(DecisionTask task, out string startingInput, out List<ActivityState> activityStates)
        {
            startingInput = null;
            activityStates = new List<ActivityState>();

            HistoryIterator iterator = new HistoryIterator(this.Client, task);
            foreach (var evnt in iterator)
            {
                if (evnt.EventType == EventType.WorkflowExecutionStarted)
                {
                    startingInput = evnt.WorkflowExecutionStartedEventAttributes.Input;  //this.Deserialize<WorkFlowExecutionInput>(evnt.WorkflowExecutionStartedEventAttributes.Input);
                }
                if (evnt.EventType == EventType.ActivityTaskCompleted)
                {
                    ActivityState state = this.Deserialize<ActivityState>(evnt.ActivityTaskCompletedEventAttributes.Result);
                    activityStates.Add(state);
                }
            }

        }
Exemplo n.º 4
0
        /// <summary>
        /// Process the history of events to find all completed activity events and the start event. Using that we can find out
        /// what image is being resized and what images still need to be completed.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="startingInput"></param>
        /// <param name="activityStates"></param>
        void ProcessHistory(DecisionTask task, out Common.WorkflowExecutionStartedInput startingInput, out List<Common.ActivityTaskCompletedResult> activityStates)
        {
            startingInput = null;
            activityStates = new List<Common.ActivityTaskCompletedResult>();

            Dictionary<long, Common.ActivityTaskCompletedResult> timerActivityStates = new Dictionary<long, Common.ActivityTaskCompletedResult>();

            Shared.HistoryIterator iterator = new Shared.HistoryIterator(this._swfClient, task);
            foreach (var evnt in iterator)
            {
                if (evnt.EventType == EventType.TimerStarted)
                {
                    timerActivityStates.Add(long.Parse(evnt.TimerStartedEventAttributes.TimerId), Common.Utils.DeserializeFromJSON<Common.ActivityTaskCompletedResult>(evnt.TimerStartedEventAttributes.Control));
                }
                if (evnt.EventType == EventType.TimerFired)
                {
                    activityStates.Add(timerActivityStates[long.Parse(evnt.TimerFiredEventAttributes.TimerId)]);
                }
                if (evnt.EventType == EventType.WorkflowExecutionStarted)
                {
                    startingInput = Common.Utils.DeserializeFromJSON<Common.WorkflowExecutionStartedInput>(evnt.WorkflowExecutionStartedEventAttributes.Input);
                }
                if (evnt.EventType == EventType.ActivityTaskCompleted)
                {
                    Common.ActivityTaskCompletedResult state = Common.Utils.DeserializeFromJSON<Common.ActivityTaskCompletedResult>(evnt.ActivityTaskCompletedEventAttributes.Result);
                    activityStates.Add(state);
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Looks at the events on the task to find all the completed activities. Using the list of completed activites it figures out
        ///  what thumbnail hasn't been created yet and create a decision to start an activity task for that image size.
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        List<Decision> Decide(DecisionTask task)
        {
            Console.WriteLine("Processing decision task ...");
            List<Decision> decisions = new List<Decision>();

            List<Common.ActivityTaskCompletedResult> activityStates;
            Common.WorkflowExecutionStartedInput startingInput;
            ProcessHistory(task, out startingInput, out activityStates);

            //get the current request...
            Request RequestCurrent = _tracker.GetRequestWithActions(startingInput.RequestId);

            //if the request has no current state. initialize the request...
            if (RequestCurrent.CurrentStateId == null)
            {
                _tracker.RequestInitialize(startingInput.RequestId);

                //the request should have a new state and actions...
                //RequestCurrent = _tracker.GetRequestWithActions(startingInput.RequestId);

                //code to tell SWF to fire activity for the new state
                //decisions.Add(CreateActivityDecision(startingInput, RequestCurrent.RequestActions.Where(x => (x.ActionTypeId == Common.Constants.AWSActivityTypeId) && x.IsActive && !x.IsComplete).FirstOrDefault().RequestActionId ?? 0));
                decisions = DecideHelper(startingInput, activityStates);
            }

            //compare the "active" SWF request actions that are not "complete" against the history
            //this line finds the "intersection" of those two lists
            //(filter this list down to only Simple Workflow actions)
            List<Common.ActivityTaskCompletedResult> results = activityStates.Join(RequestCurrent.RequestActions.Where(x => (x.ActionTypeId == Common.Constants.AWSActivityTypeId || x.ActionTypeId == 2) && x.IsActive && !x.IsComplete).ToList(), a => a.RequestActionId, b => b.RequestActionId, (c, d) => c).ToList();

            //mark any "active" but not "complete" request actions as "complete"
            foreach (Common.ActivityTaskCompletedResult result in results)
            {
                _tracker.RequestActionComplete(result.RequestActionId);
            }

            //check whether the request's actions have reached a point where a transition can be followed...
            Transition Transition = _tracker.GetCompletedTransitionForRequest(startingInput.RequestId);

            //if a transition can be followed...
            if (Transition != null)
            {
                //follow the transition
                _tracker.RequestFollowTransition(startingInput.RequestId, Transition.TransitionId);

                ////the request should have a new state and actions now...
                //RequestCurrent = _tracker.GetRequestWithActions(startingInput.RequestId);

                //IEnumerable<RequestAction> ActiveNotComplete = RequestCurrent.RequestActions.Where(x => (x.ActionTypeId == Common.Constants.AWSActivityTypeId || x.ActionTypeId == 2) && x.IsActive && !x.IsComplete);

                ////if a request action was found that was "active" but not "complete" it must be run now
                //if (ActiveNotComplete.Count() != 0)
                //{

                //    //iterate through the active but not complete actions...
                //    foreach (RequestAction ra in ActiveNotComplete)
                //    {

                //        if (ra.ActionTypeId == 1) //if state completed...
                //        {
                //            //code to tell SWF to fire activity for the new state
                //            decisions.Add(CreateActivityDecision(startingInput, ra.RequestActionId ?? 0));
                //        }
                //        if (ra.ActionTypeId == 2) //if timer
                //        {
                //            // setup the input for the activity task.
                //            Common.ActivityTaskCompletedResult state = new Common.ActivityTaskCompletedResult
                //            {
                //                StartingInput = startingInput,
                //                RequestActionId = ra.RequestActionId ?? 0
                //            };

                //            Decision decision = new Decision()
                //            {
                //                DecisionType = DecisionType.StartTimer,
                //                StartTimerDecisionAttributes = new StartTimerDecisionAttributes()
                //                {
                //                    Control = Common.Utils.SerializeToJSON<Common.ActivityTaskCompletedResult>(state),
                //                    StartToFireTimeout = "3",
                //                    TimerId = DateTime.Now.Ticks.ToString()
                //                }
                //            };

                //            decisions.Add(decision);
                //        }

                //    }
                //}
                //else
                //{
                //    Console.WriteLine("Workflow execution complete for " + startingInput.RequestId);
                //    //code to tell SWF to complete workflow execution
                //    decisions.Add(CreateCompleteWorkflowExecutionDecision(activityStates));
                //}
                decisions = DecideHelper(startingInput, activityStates);
            }

            //// Loop through all the diffrent image sizes the workflow will create and
            //// when we find one missing create that activity task for the missing image.
            ////
            //// To keep the sample simple each activity is scheduled one at a time. For better performance
            //// the activities could be scheduled in parallel and then use the decider to check if all the activities
            //// have been completed.
            //for (int size = 256; size >= 16; size /= 2)
            //{
            //    if (activityStates.FirstOrDefault(x => x.ImageSize == size) == null)
            //    {
            //        decisions.Add(CreateActivityDecision(startingInput, size));
            //        break;
            //    }
            //}

            //// If there were no decisions that means all the thumbnails have been created so we decided the workflow execution is complete.
            //if (decisions.Count == 0)
            //{
            //    Console.WriteLine("Workflow execution complete for " + startingInput.SourceImageKey);
            //    decisions.Add(CreateCompleteWorkflowExecutionDecision(activityStates));
            //}

            return decisions;
        }
        List<Decision> Decide(DecisionTask task)
        {
            try
            {
                List<Decision> decisions = new List<Decision>();
                var startEvent = task.Events.FirstOrDefault(x => x.EventType == EventType.WorkflowExecutionStarted);
                if (startEvent != null)
                {
                    var pollId = startEvent.WorkflowExecutionStartedEventAttributes.Input;
                    Logger.LogMessage("Processing decision task for poll id: " + pollId);

                    var poll = PollProcessor.Instance.GetPollAsync(pollId).Result;

                    if (poll != null)
                    {
                        if (poll.State == PollDefinition.POLL_STATE_UNSCHEDULE && DateTime.Now < poll.StartTime)
                        {
                            // Add second to compensate for the rounding
                            var timeDelay = (int)(new TimeSpan(poll.StartTime.Ticks - DateTime.Now.Ticks).TotalSeconds) + 1;
                            var decision = new Decision
                            {
                                DecisionType = DecisionType.StartTimer,
                                StartTimerDecisionAttributes = new StartTimerDecisionAttributes
                                {
                                    StartToFireTimeout = timeDelay.ToString(),
                                    TimerId = Guid.NewGuid().ToString()
                                }
                            };
                            decisions.Add(decision);
                            PollProcessor.Instance.UpdatePollStateAsync(pollId, PollDefinition.POLL_STATE_SCHEDULE).Wait();
                            Logger.LogMessage("Scheduled timer for {0} seconds till activating poll.", timeDelay);
                        }
                        else if (poll.State == PollDefinition.POLL_STATE_SCHEDULE)
                        {
                            Decision decision = new Decision()
                            {
                                DecisionType = DecisionType.ScheduleActivityTask,
                                ScheduleActivityTaskDecisionAttributes = new ScheduleActivityTaskDecisionAttributes()
                                {
                                    ActivityType = new ActivityType()
                                    {
                                        Name = Constants.SWF_ACTIVTY_START_TIMER_EXPIRED,
                                        Version = Constants.SWF_ACTIVTY_START_TIMER_EXPIRED_VERSION
                                    },
                                    TaskList = new TaskList
                                    {
                                        Name = Constants.SWF_ACTIVTY_START_TIMER_EXPIRED_TASKLIST
                                    },
                                    HeartbeatTimeout = Constants.SWF_TIMEOUT,
                                    ScheduleToCloseTimeout = Constants.SWF_TIMEOUT,
                                    ScheduleToStartTimeout = Constants.SWF_TIMEOUT,
                                    StartToCloseTimeout = Constants.SWF_TIMEOUT,
                                    ActivityId = string.Format("{0}:{1}", Constants.SWF_ACTIVTY_START_TIMER_EXPIRED, DateTime.Now.Ticks),
                                    Input = poll.Id
                                }
                            };
                            decisions.Add(decision);
                            Logger.LogMessage("Start timer complete now deciding to run the {0} activity to activate poll.", Constants.SWF_ACTIVTY_START_TIMER_EXPIRED);
                        }
                        else if (poll.State == PollDefinition.POLL_STATE_ACTIVE && DateTime.Now < poll.EndTime)
                        {
                            // Add second to compensate for the rounding
                            var timeDelay = (int)(new TimeSpan(poll.EndTime.Ticks - DateTime.Now.Ticks).TotalSeconds) + 1;
                            var decision = new Decision
                            {
                                DecisionType = DecisionType.StartTimer,
                                StartTimerDecisionAttributes = new StartTimerDecisionAttributes
                                {
                                    StartToFireTimeout = timeDelay.ToString(),
                                    TimerId = Guid.NewGuid().ToString()
                                }
                            };
                            decisions.Add(decision);
                            Logger.LogMessage("Scheduled timer for {0} seconds till poll expires.", timeDelay);
                        }
                        else if (poll.State == PollDefinition.POLL_STATE_ACTIVE)
                        {
                            Decision decision = new Decision()
                            {
                                DecisionType = DecisionType.ScheduleActivityTask,
                                ScheduleActivityTaskDecisionAttributes = new ScheduleActivityTaskDecisionAttributes()
                                {
                                    ActivityType = new ActivityType()
                                    {
                                        Name = Constants.SWF_ACTIVTY_END_TIMER_EXPIRED,
                                        Version = Constants.SWF_ACTIVTY_END_TIMER_EXPIRED_VERSION
                                    },
                                    TaskList = new TaskList
                                    {
                                        Name = Constants.SWF_ACTIVTY_END_TIMER_EXPIRED_TASKLIST
                                    },
                                    HeartbeatTimeout = Constants.SWF_TIMEOUT,
                                    ScheduleToCloseTimeout = Constants.SWF_TIMEOUT,
                                    ScheduleToStartTimeout = Constants.SWF_TIMEOUT,
                                    StartToCloseTimeout = Constants.SWF_TIMEOUT,
                                    ActivityId = string.Format("{0}:{1}", Constants.SWF_ACTIVTY_END_TIMER_EXPIRED, DateTime.Now.Ticks),
                                    Input = poll.Id
                                }
                            };
                            decisions.Add(decision);
                            Logger.LogMessage("End timer complete now deciding to run the {0} activity to expire poll.", Constants.SWF_ACTIVTY_END_TIMER_EXPIRED);
                        }
                    }
                }

                if (decisions.Count == 0)
                {
                    Decision decision = new Decision()
                    {
                        DecisionType = DecisionType.CompleteWorkflowExecution,
                        CompleteWorkflowExecutionDecisionAttributes = new CompleteWorkflowExecutionDecisionAttributes
                        {
                        }
                    };
                    decisions.Add(decision);
                    Logger.LogMessage("Workflow execution complete for {0}", task.WorkflowExecution.WorkflowId);
                }

                return decisions;
            }
            catch(Exception e)
            {
                string message = string.Format("Error processing work flow execution {0} and is being aborted: {1}\n", task.WorkflowExecution.WorkflowId, e.Message, e.StackTrace);
                Logger.LogMessage(message);
                Decision decision = new Decision()
                {
                    DecisionType = DecisionType.CompleteWorkflowExecution,
                    CompleteWorkflowExecutionDecisionAttributes = new CompleteWorkflowExecutionDecisionAttributes
                    {
                        Result = message
                    }
                };
                return new List<Decision> { decision };                
            }
        }