/// <summary> /// Finilizes the Workflow completion with backend. /// Perform Workflow History Cleanup based on retention policy. /// </summary> /// <param name="wf"></param> /// <param name="Result"></param> /// <returns></returns> public bool WorkflowFinalize(Workflow wf, WfResult Result) { if (wf == null || wf.RunId == 0) { throw new InvalidDataException("Workflow object can not be finalized"); } short status_id = DBStatus.WfValue(Result.StatusCode); string cmd_text = String.Format(WORKFLOW_FINALIZE_QUERY, wf.WorkflowId, wf.RunId, status_id, wf.HistoryRetention, ((_debug) ? 1 : 0)); ExecuteNonQuery(cmd_text); return(true); }
/// <summary> /// Reports execution results to the backend /// </summary> /// <param name="wfs"></param> /// <param name="Result"></param> /// <returns></returns> public bool WorkflowStepStatusSet(WorkflowStep wfs, WfResult Result) { if (wfs == null || wfs.RunId == 0) { throw new InvalidDataException("WorkflowStep object is not in the correct state"); } short status_id = DBStatus.WfValue(Result.StatusCode); string cmd_text = String.Format(WORKFLOW_STEP_STATUS_SET_QUERY, wfs.WorkflowId, wfs.StepId, wfs.RunId, status_id, Result.ErrorCode); ExecuteNonQuery(cmd_text); return(true); }
/// <summary> /// Cancel the Batch(StepId = 0)/Step on the ExitEvent /// </summary> /// <param name="WfId"></param> /// <param name="StepId"></param> /// <param name="RunId"></param> /// <param name="LoopGroup"></param> public WfResult WorkflowExitEventCheck(int WfId, int StepId, int RunId) { string cmd_text = String.Format(WORKFLOW_EXIT_EVENT_QUERY, WfId, StepId, RunId); var ret = ExecuteScalar(cmd_text); if (ret == null) { return(WfResult.Unknown); } WfResult result; switch (DBStatus.DbValue((short)ret)) { case WfStatus.Unknown: case WfStatus.Running: result = WfResult.Started; break; case WfStatus.Failed: result = WfResult.Create(WfStatus.Failed, "Canceled", 0); break; case WfStatus.Succeeded: result = WfResult.Create(WfStatus.Succeeded, "Canceled", 0); break; default: result = WfResult.Started; break; } return(result); }
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); }
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); }
public void SetTo(WfResult result) { this.StatusCode = result.StatusCode; this.Message = result.Message; this.ErrorCode = result.ErrorCode; }
public static WfResult Create(WfResult result) { return(new WfResult(result.StatusCode, result.Message, result.ErrorCode)); }