public IEnumerable <TransitionRecord> GetInboundTransitions(ActivityRecord activityRecord)
 {
     return(_workflowRecord.WorkflowDefinitionRecord
            .TransitionRecords
            .Where(transition =>
                   transition.DestinationActivityRecord == activityRecord
                   ).ToArray());
 }
 public IEnumerable <TransitionRecord> GetOutboundTransitions(ActivityRecord activityRecord, LocalizedString outcome)
 {
     return(_workflowRecord.WorkflowDefinitionRecord
            .TransitionRecords
            .Where(transition =>
                   transition.SourceActivityRecord == activityRecord &&
                   transition.SourceEndpoint == outcome.TextHint
                   ).ToArray());
 }
Пример #3
0
        public IEnumerable<ActivityRecord> ExecuteWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens)
        {
            var firstPass = true;
            var scheduled = new Stack<ActivityRecord>();

            scheduled.Push(activityRecord);

            var blocking = new List<ActivityRecord>();

            while (scheduled.Any()) {

                activityRecord = scheduled.Pop();

                var activityContext = CreateActivityContext(activityRecord, tokens);

                // while there is an activity to process

                if (!firstPass){
                    if (activityContext.Activity.IsEvent) {
                        blocking.Add(activityRecord);
                        continue;
                    }
                }
                else {
                    firstPass = false;
                }

                // signal every activity that the activity is about to be executed
                var cancellationToken = new CancellationToken();
                InvokeActivities(activity => activity.OnActivityExecuting(workflowContext, activityContext, cancellationToken));

                if (cancellationToken.IsCancelled) {
                    // activity is aborted
                    continue;
                }

                var outcomes = activityContext.Activity.Execute(workflowContext, activityContext).ToList();

                // signal every activity that the activity is executed
                InvokeActivities(activity => activity.OnActivityExecuted(workflowContext, activityContext));

                foreach (var outcome in outcomes) {
                    // look for next activity in the graph
                    var transition = workflowContext.Record.WorkflowDefinitionRecord.TransitionRecords.FirstOrDefault(x => x.SourceActivityRecord == activityRecord && x.SourceEndpoint == outcome.TextHint);

                    if (transition != null) {
                        scheduled.Push(transition.DestinationActivityRecord);
                    }
                }
            }

            // apply Distinct() as two paths could block on the same activity
            return blocking.Distinct();
        }
Пример #4
0
        public override void Execute(RecipeExecutionContext context) {
            foreach (var workflowDefinitionElement in context.RecipeStep.Step.Elements()) {
                var workflowName = workflowDefinitionElement.Attribute("Name").Value;
                Logger.Information("Importing workflow '{0}'.", workflowName);

                try {
                    var workflowDefinition = GetOrCreateWorkflowDefinition(workflowName);
                    var activitiesElement = workflowDefinitionElement.Element("Activities");
                    var transitionsElement = workflowDefinitionElement.Element("Transitions");
                    var activitiesDictionary = new Dictionary<int, ActivityRecord>();

                    workflowDefinition.Enabled = Boolean.Parse(workflowDefinitionElement.Attribute("Enabled").Value);

                    foreach (var activityElement in activitiesElement.Elements()) {
                        var localId = Int32.Parse(activityElement.Attribute("Id").Value);
                        var activityName = activityElement.Attribute("Name").Value;
                        Logger.Information("Importing activity '{0}' with ID '{1}'.", activityName, localId);
                        var activity = new ActivityRecord {
                            Name = activityName,
                            Start = Boolean.Parse(activityElement.Attribute("Start").Value),
                            X = Int32.Parse(activityElement.Attribute("X").Value),
                            Y = Int32.Parse(activityElement.Attribute("Y").Value),
                            State = activityElement.Element("State").Value
                        };

                        activitiesDictionary.Add(localId, activity);
                        workflowDefinition.ActivityRecords.Add(activity);
                    }

                    foreach (var transitionElement in transitionsElement.Elements()) {
                        var sourceActivityId = Int32.Parse(transitionElement.Attribute("SourceActivityId").Value);
                        var sourceEndpoint = transitionElement.Attribute("SourceEndpoint").Value;
                        var destinationActivityId = Int32.Parse(transitionElement.Attribute("DestinationActivityId").Value);
                        var destinationEndpoint = transitionElement.Attribute("DestinationEndpoint").Value;
                        Logger.Information("Importing transition between activities '{0}' and '{1}'.", sourceActivityId, destinationActivityId);

                        workflowDefinition.TransitionRecords.Add(new TransitionRecord {
                            SourceActivityRecord = activitiesDictionary[sourceActivityId],
                            SourceEndpoint = sourceEndpoint,
                            DestinationActivityRecord = activitiesDictionary[destinationActivityId],
                            DestinationEndpoint = destinationEndpoint
                        });
                    }
                }
                catch (Exception ex) {
                    Logger.Error(ex, "Error while importing workflow '{0}'.", workflowName);
                    throw;
                }
            }
        }
Пример #5
0
        public void ExecuteRecipeStep(RecipeContext recipeContext) {
            if (!String.Equals(recipeContext.RecipeStep.Name, "Workflows", StringComparison.OrdinalIgnoreCase)) {
                return;
            }

            foreach (var workflowDefinitionElement in recipeContext.RecipeStep.Step.Elements()) {
                var workflowDefinition = new WorkflowDefinitionRecord {
                    Name = ProbeWorkflowDefinitionName(workflowDefinitionElement.Attribute("Name").Value),
                    Enabled = Boolean.Parse(workflowDefinitionElement.Attribute("Enabled").Value)
                };
                
                _workflowDefinitionRepository.Create(workflowDefinition);

                var activitiesElement = workflowDefinitionElement.Element("Activities");
                var transitionsElement = workflowDefinitionElement.Element("Transitions");
                var activitiesDictionary = new Dictionary<int, ActivityRecord>();

                foreach (var activityElement in activitiesElement.Elements()) {
                    var localId = Int32.Parse(activityElement.Attribute("Id").Value);
                    var activity = new ActivityRecord {
                        Name = activityElement.Attribute("Name").Value,
                        Start = Boolean.Parse(activityElement.Attribute("Start").Value),
                        X = Int32.Parse(activityElement.Attribute("X").Value),
                        Y = Int32.Parse(activityElement.Attribute("Y").Value),
                        State = activityElement.Element("State").Value
                    };

                    activitiesDictionary.Add(localId, activity);
                    workflowDefinition.ActivityRecords.Add(activity);
                }

                foreach (var transitionElement in transitionsElement.Elements()) {
                    var sourceActivityId = Int32.Parse(transitionElement.Attribute("SourceActivityId").Value);
                    var sourceEndpoint = transitionElement.Attribute("SourceEndpoint").Value;
                    var destinationActivityId = Int32.Parse(transitionElement.Attribute("DestinationActivityId").Value);
                    var destinationEndpoint = transitionElement.Attribute("DestinationEndpoint").Value;

                    workflowDefinition.TransitionRecords.Add(new TransitionRecord {
                        SourceActivityRecord = activitiesDictionary[sourceActivityId],
                        SourceEndpoint = sourceEndpoint,
                        DestinationActivityRecord = activitiesDictionary[destinationActivityId],
                        DestinationEndpoint = destinationEndpoint
                    });
                }
            }

            recipeContext.Executed = true;
        }
Пример #6
0
        private void StartWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens) {
            
            // signal every activity that the workflow is about to start
            var cancellationToken = new CancellationToken();
            InvokeActivities(activity => activity.OnWorkflowStarting(workflowContext, cancellationToken));

            if (cancellationToken.IsCancelled) {
                // workflow is aborted
                return;
            }

            // signal every activity that the workflow is has started
            InvokeActivities(activity => activity.OnWorkflowStarted(workflowContext));
            
            var blockedOn = ExecuteWorkflow(workflowContext, activityRecord, tokens).ToList();

            // is the workflow halted on a blocking activity ?
            if (!blockedOn.Any()) {
                // no, nothing to do
            }
            else {
                // workflow halted, create a workflow state
                _workflowRepository.Create(workflowContext.Record);

                foreach (var blocking in blockedOn) {
                    workflowContext.Record.AwaitingActivities.Add(new AwaitingActivityRecord {
                        ActivityRecord = blocking,
                        WorkflowRecord = workflowContext.Record
                    });
                }
            }
        }
Пример #7
0
 private ActivityContext CreateActivityContext(ActivityRecord activityRecord, IDictionary<string, object> tokens) {
     return new ActivityContext {
         Record = activityRecord,
         Activity = _activitiesManager.GetActivityByName(activityRecord.Name),
         State = new Lazy<dynamic>(() => GetState(activityRecord.State, tokens))
     };
 }
 private string KeyFor(ActivityRecord record, string key)
 {
     return("@" + record.Id + "_" + key);
 }
 public object GetStateFor(ActivityRecord record, string key)
 {
     return(GetStateFor <object>(record, key));
 }
 public T GetStateFor <T>(ActivityRecord record, string key)
 {
     return(GetState <T>(KeyFor(record, key)));
 }
 public bool HasStateFor(ActivityRecord record, string key)
 {
     return(GetState(KeyFor(record, key)) != null);
 }
 public void SetStateFor <T>(ActivityRecord record, string key, T value)
 {
     SetState(KeyFor(record, key), value);
 }