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()); }
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(); }
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; } } }
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; }
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 }); } } }
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); }