internal SequentialWorkflowActivity(IWorkflow workflow, MethodBase method, IWorkflowActivity previous) { Workflow = workflow; Method = method; PreviousActivity = previous; Key = Guid.NewGuid().ToString("N"); }
public IWorkflowActivity Activate() { IWorkflowActivity activity = null; try { _logger.Information("Activate Activity {0}", _process.Process); activity = LoadActivity(); //get the list of the required attributes from Activity List <string> required = new List <string>(activity.RequiredAttributes); //check if we have what we need WorkflowActivityArgs activity_args = new WorkflowActivityArgs(); if (!ProcessAttributeRequest(activity_args, required)) { throw new Exception("Not all requested Attributes are available"); } activity_args.Logger = _logger; activity.Configure(activity_args); } catch (Exception ex) { //result = WfResult.Create(WfStatus.Failed, ex.Message, -5); throw ex; } return(activity); }
private static IWorkflowActivity FindActivity(string activityKey, IWorkflowActivity activity) { if (activity != null && activity.Key != activityKey) { if (activity is IWorkflowConditionalActivity) { var condition = activity as IWorkflowConditionalActivity; activity = FindActivity(activityKey, condition.IfTrueActivity) ?? FindActivity(activityKey, condition.ElseActivity) ?? FindActivity(activityKey, condition.NextActivity); } else { activity = FindActivity(activityKey, activity.NextActivity); } } return(activity); }
private Func <ActionResult> OnSuccess(IWorkflowActivity currentActivity, object @return) { return(() => { var nextActivity = currentActivity.NextActivity; if (nextActivity != null) { if (nextActivity is IWorkflowConditionalActivity) { var condition = nextActivity as IWorkflowConditionalActivity; nextActivity = condition.Condition(@return) ? condition.IfTrueActivity : condition.ElseActivity; } var values = new RouteValueDictionary(new { workflowKey = nextActivity.Workflow.Key, activityKey = nextActivity.Key, modelType = nextActivity.Method.DeclaringType.PartialName(), methodName = nextActivity.Method.Name, index = 0 }); WorkflowBindingParameterValueProvider.BindingParameters.Clear(); if (nextActivity.Binding != null) { var binding = nextActivity.Binding(@return); if (binding != null) { foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(binding)) { WorkflowBindingParameterValueProvider.BindingParameters.Add(prop.Name, prop.GetValue(binding)); } } } return RedirectToAction(RunningObjectsAction.Execute.ToString(), values); } return GetRedirectOnFinish(); }); }
private Func <object, ActionResult> OnSuccessWithReturn(IWorkflowActivity nextActivity) { return(@return => OnSuccess(nextActivity, @return)()); }
private IWorkflowActivity LoadActivity() { string activity_path = String.Empty; if (_attributes.Keys.Contains(ACTIVITY_LOCATION)) { activity_path = _attributes[ACTIVITY_LOCATION]; } string[] activity_name = _process.Process.Split('.'); string activity_dll = activity_name[0] + ".dll"; string activity_namespace = String.Empty; for (int i = 1; i < activity_name.Length - 1; i++) { activity_namespace += ((i == 1) ? "" : ".") + activity_name[i]; } string activity_classname = activity_name[activity_name.Length - 1]; string dll_path = System.IO.Path.Combine(activity_path, activity_dll); string path = System.IO.Path.GetFullPath(dll_path); IWorkflowActivity activity = null; try { // Load dll Assembly assembly = Assembly.LoadFile(path); // Look for the interface foreach (Type item in assembly.GetTypes()) { if (!item.IsClass) { continue; } if (!(item.Namespace == activity_namespace && item.Name == activity_classname)) { continue; } if (item.GetInterfaces().Contains(typeof(IWorkflowActivity))) { activity = (IWorkflowActivity)Activator.CreateInstance(item); break; } } } catch (Exception ex) { string message = ex.Message; ReflectionTypeLoadException tex = ex as ReflectionTypeLoadException; if (tex != null && tex.LoaderExceptions != null) { foreach (Exception lex in tex.LoaderExceptions) { message += " " + lex.Message; } } throw new Exception(string.Format("Error loading activity DLL {0}: {1}!", path, message)); } // no IWorkflowActivity interface if (activity == null) { throw new Exception(string.Format("IWorkflowActivity interface is missing {0}!", path)); } return(activity); }
public SequentialWorkflowConditionalActivity(IWorkflow workflow, Func<object, bool> condition, IWorkflowActivity previousActivity) : base(workflow, null, previousActivity) { Condition = condition; }
public WfResult Run(CancellationToken extToken) { _logger.Information("Start Processing Workflow Constraint {ItemKey}", _item.Key); WfResult result = WfResult.Unknown; WorkflowAttributeCollection attributes = _db.WorkflowAttributeCollectionGet(_item.WorkflowId, _item.StepId, _item.ConstId, _item.RunId); attributes.Merge(_wfp.Attributes); WorkflowActivity activity = new WorkflowActivity(_item.Process, attributes, _logger); TimeSpan timeout = TimeSpan.FromSeconds((_item.WaitPeriod <= 0) ? 7200 : _item.WaitPeriod); TimeSpan sleep = TimeSpan.FromSeconds((_item.Ping <= 0) ? 30 : _item.Ping); try { using (CancellationTokenSource timeoutCts = new CancellationTokenSource(timeout)) using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(extToken, timeoutCts.Token)) { Task <WfResult> task = Task.Factory.StartNew(() => { WfResult const_result = WfResult.Unknown; IWorkflowActivity runner = activity.Activate(); while (true) { //Run constraint activity using (linkedCts.Token.Register(Thread.CurrentThread.Abort)) { try { //do thread hard abort if it is stuck on Run //constraint logic should never allow this to happen thou const_result = runner.Run(linkedCts.Token); _logger.Debug("Constraint {ItemKey} current status = {WfStatus}", _item.Key, const_result.StatusCode.ToString()); if (const_result.StatusCode != WfStatus.Waiting) { break; } } catch (ThreadAbortException ex) { throw ex; } } //cts.Token.ThrowIfCancellationRequested(); Task.Delay(sleep, linkedCts.Token).Wait(); if (linkedCts.IsCancellationRequested) { const_result = WfResult.Canceled; break; } } return(const_result); }, linkedCts.Token); result = task.Result; } } catch (AggregateException ex) { //result = WfResult.Create(WfStatus.Failed,"timeout",-3); throw ex; } finally { _logger.Information("Finish Processing Workflow Constraint {ItemKey} with result - {WfStatus}", _item.Key, result.StatusCode.ToString()); } return(result); }
private IWorkflowActivity StartAt(MethodBase method) { return(StartActivity = new SequentialWorkflowActivity(this, method, null)); }
public SequentialWorkflowConditionalActivity(IWorkflow workflow, Func <object, bool> condition, IWorkflowActivity previousActivity) : base(workflow, null, previousActivity) { Condition = condition; }
private static IWorkflowActivity FindActivity(string activityKey, IWorkflowActivity activity) { if (activity != null && activity.Key != activityKey) { if (activity is IWorkflowConditionalActivity) { var condition = activity as IWorkflowConditionalActivity; activity = FindActivity(activityKey, condition.IfTrueActivity) ?? FindActivity(activityKey, condition.ElseActivity) ?? FindActivity(activityKey, condition.NextActivity); } else activity = FindActivity(activityKey, activity.NextActivity); } return activity; }
private Func<object, ActionResult> OnSuccessWithReturn(IWorkflowActivity nextActivity) { return @return => OnSuccess(nextActivity, @return)(); }
private Func<ActionResult> OnSuccess(IWorkflowActivity currentActivity, object @return) { return () => { var nextActivity = currentActivity.NextActivity; if (nextActivity != null) { if (nextActivity is IWorkflowConditionalActivity) { var condition = nextActivity as IWorkflowConditionalActivity; nextActivity = condition.Condition(@return) ? condition.IfTrueActivity : condition.ElseActivity; } var values = new RouteValueDictionary(new { workflowKey = nextActivity.Workflow.Key, activityKey = nextActivity.Key, modelType = nextActivity.Method.DeclaringType.PartialName(), methodName = nextActivity.Method.Name, index = 0 }); WorkflowBindingParameterValueProvider.BindingParameters.Clear(); if (nextActivity.Binding != null) { var binding = nextActivity.Binding(@return); if (binding != null) { foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(binding)) WorkflowBindingParameterValueProvider.BindingParameters.Add(prop.Name, prop.GetValue(binding)); } } return RedirectToAction(RunningObjectsAction.Execute.ToString(), values); } return GetRedirectOnFinish(); }; }
public WfResult Run(CancellationToken extToken) { _logger.Information("Start Processing Workflow step {ItemKey}:{ItemName}", _step.Key, _step.StepName); WfResult result = WfResult.Succeeded; try { //Step Constraints if (_step.StepConstraints != null) { foreach (WorkflowConstraint wfc in _step.StepConstraints) { if (wfc.IsDisabled || wfc.Process.ProcessId == 0) { _logger.Debug("Constraint process is not defined or disabled {ItemKey}:{ItemName}", _step.Key, _step.StepName); continue; } if ((wfc.Process.ScopeId & 12) == 0) { throw new ArgumentException(String.Format("Constraint Process is not of correct scope 0011 = {0}", wfc.Process.ScopeId)); } wfc.WorkflowId = _step.WorkflowId; wfc.StepId = _step.StepId; wfc.RunId = _step.RunId; WorkflowConstraintProcessor wcp = new WorkflowConstraintProcessor(wfc, _wfp); result = wcp.Run(extToken); if (result.StatusCode == WfStatus.Failed) { _logger.Error("Workflow step {ItemKey}:{ItemName} failed with: {ErrorCode}", _step.Key, _step.StepName, result.Message, result.ErrorCode); return(result); } } } WorkflowAttributeCollection attributes = null; if (_step.StepProcess != null) { //always evaluate step attributes attributes = _db.WorkflowAttributeCollectionGet(_step.WorkflowId, _step.StepId, 0, _step.RunId); attributes.Merge(_wfp.Attributes); if (_step.StepProcess.ProcessId != 0) { if ((_step.StepProcess.ScopeId & 3) == 0) { throw new ArgumentException(String.Format("Step Process is not of correct scope 1100 = {0}", _step.StepProcess.ScopeId)); } //Run Step Activity here WorkflowActivity step_activity = new WorkflowActivity(_step.StepProcess, attributes, _logger); IWorkflowActivity step_runner = step_activity.Activate(); result = (ProcessRunAsync(step_runner, extToken, _step.StepRetry, _step.StepDelayOnRetry, _step.StepTimeout, _logger)).Result; } else { _logger.Debug("Step process is not defined. Skipped {ItemKey}", _step.Key); } } if (result.StatusCode == WfStatus.Succeeded && _step.StepOnSuccessProcess != null) { _logger.Information("On step success"); _logger.Debug("On success process - {ProcessName}", _step.StepOnSuccessProcess.Process); if ((_step.StepOnSuccessProcess.ScopeId & 3) == 0) { throw new ArgumentException(String.Format("OnSuccess Process is not of correct scope 1100 = {0}", _step.StepOnSuccessProcess.ScopeId)); } //Run OnSuccess Activity here //re-evaluate attribites //if (attributes == null) attributes = _db.WorkflowAttributeCollectionGet(_step.WorkflowId, _step.StepId, 0, _step.RunId); WorkflowActivity success_activity = new WorkflowActivity(_step.StepOnSuccessProcess, attributes, _logger); IWorkflowActivity success_runner = success_activity.Activate(); WfResult task_result = (ProcessRunAsync(success_runner, extToken, 0, 0, _step.StepTimeout, _logger)).Result; if (task_result.StatusCode == WfStatus.Failed) { result = task_result; } } else if (result.StatusCode == WfStatus.Failed && _step.StepOnFailureProcess != null) { _logger.Information("On step failure"); _logger.Debug("On failure process - {ProcessName}", _step.StepOnFailureProcess.Process); if ((_step.StepOnFailureProcess.ScopeId & 3) == 0) { throw new ArgumentException(String.Format("OnFailure Process is not of correct scope 1100 = {0}", _step.StepOnFailureProcess.ScopeId)); } //Run OnFailure Activity here //re-evaluate attribites //if (attributes == null) attributes = _db.WorkflowAttributeCollectionGet(_step.WorkflowId, _step.StepId, 0, _step.RunId); WorkflowActivity failure_activity = new WorkflowActivity(_step.StepOnFailureProcess, attributes, _logger); IWorkflowActivity failure_runner = failure_activity.Activate(); WfResult task_result = (ProcessRunAsync(failure_runner, extToken, 0, 0, _step.StepTimeout, _logger)).Result; if (task_result.StatusCode == WfStatus.Failed) { result = task_result; } } } catch (AggregateException aex) { _logger.Error(aex, "AggregateException: {Message}", aex.Message); foreach (var ex in aex.InnerExceptions) { _logger.Error(ex, "InnerException: {Message}", ex.Message); } result = WfResult.Create(WfStatus.Failed, aex.Message, -10); } catch (Exception ex) { _logger.Error(ex, "Exception: {0}", ex.Message); result = WfResult.Create(WfStatus.Failed, ex.Message, -10); } _logger.Information("Workflow step {ItemKey}:{ItemName} finished with result {WfStatus}", _step.Key, _step.StepName, result.StatusCode.ToString()); return(result); }
private async Task <WfResult> ProcessRunAsync(IWorkflowActivity runner, CancellationToken token, int retry, int delay, int timeout, ILogger logger) { return(await Task.Factory.StartNew(() => { WfResult result = WfResult.Failed; //do thread hard abort if it is stuck on Run //using (token.Register(Thread.CurrentThread.Abort)) //{ for (int i = 0; i <= retry; i++) { using (CancellationTokenSource timeoutCts = new CancellationTokenSource()) using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutCts.Token)) { if (timeout > 0) { timeoutCts.CancelAfter(TimeSpan.FromSeconds(timeout)); } try { token.ThrowIfCancellationRequested(); if (i > 0) { logger.Information("Retry attempt {Count} on: {Message}", i, result.Message); if (delay > 0) { Task.Delay(TimeSpan.FromSeconds(delay), token).Wait(); } } result = runner.Run(linkedCts.Token); } catch (ThreadAbortException ex) { logger.Error(ex, "ThreadAbortException: {0}", ex.Message); result = WfResult.Create(WfStatus.Failed, ex.Message, -10); } catch (AggregateException aex) { logger.Error(aex, "AggregateException: {Message}", aex.Message); foreach (var ex in aex.InnerExceptions) { logger.Error(ex, "InnerException: {Message}", ex.Message); } result = WfResult.Failed; if (timeoutCts.IsCancellationRequested) { result = WfResult.Create(WfStatus.Failed, "Step was cancelled on timeout", -10); logger.Error(aex, result.Message); } if (token.IsCancellationRequested) { logger.Error(aex, "Step was cancelled"); result = WfResult.Canceled; } } catch (Exception ex) { logger.Error(ex, "Exception: {Message}", ex.Message); result = WfResult.Create(WfStatus.Failed, ex.Message, -10); } if (result.StatusCode == WfStatus.Succeeded || token.IsCancellationRequested) { break; } } } return result; //} }));//, token); }