using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using Neo.Afx.ComponentModel; using Neo.Afx.Services; namespace Neo.Afx.WinService.Workflows { public class WorkflowTaskProcessor : Worker, IExecutable { #region Handlers Dictionary _handlers; public Dictionary Handlers { get { lock(PropertyLock) { return _handlers; } } set { lock(PropertyLock) { _handlers = value; } } } #endregion #region Run public void Run() { TraceInfo = string.Empty; var trace = new StringBuilder(); using (var database = new WorkflowServiceDatabase(Settings["ConnectionString"])) { if (Handlers == null) { Handlers = new Dictionary(); #region Initialize handlers from database foreach (var handler in database.GetHandlers()) { try { Handlers.Add( handler.WorkflowTaskHandlerID, new WorkflowTask(handler.HandlerTypeName, handler.MethodName, UserID, UserEmail, handler.Settings)); } catch (Exception ex) { trace.AppendFormat("Error creating WorkflowTaskHandler ID={0} --> {1} ", handler.WorkflowTaskHandlerID, ex.ToStringComplete()); trace.AppendLine(); } } #endregion } if (Handlers.Count == 0) { TraceInfo = trace.ToString(); return; } var tasks = database.GetTasks().ToList(); if (tasks.Count == 0) { return; } foreach (var task in tasks) { if (!task.WorkflowTemplateStep.WorkflowTaskHandlerID.HasValue) { continue; } var handlerID = task.WorkflowTemplateStep.WorkflowTaskHandlerID.Value; var workflowTask = Handlers[handlerID]; short workflowInstanceTaskStatusID; string errorMessage = null; string stackTrace = null; try { workflowInstanceTaskStatusID = (short)workflowTask.Run(task.WorkflowInstanceTaskID); } catch (TargetInvocationException tiex) { workflowInstanceTaskStatusID = (short)WorkflowInstanceTaskStatusEnum.Error; errorMessage = tiex.InnerException.Message; stackTrace = tiex.InnerException.ToStringComplete(); } catch (Exception ex) { workflowInstanceTaskStatusID = (short)WorkflowInstanceTaskStatusEnum.Error; errorMessage = ex.Message; stackTrace = ex.ToStringComplete(); } if (!string.IsNullOrEmpty(workflowTask.TraceInfo)) { trace.AppendLine(string.Format("TASK[{0}]: {1}", task.WorkflowInstanceTaskID, workflowTask.TraceInfo)); } if (!string.IsNullOrEmpty(stackTrace)) { trace.AppendLine(string.Format("TASK[{0}] ERROR: {1}", task.WorkflowInstanceTaskID, stackTrace)); } // Don't update task if status is zero if (workflowInstanceTaskStatusID <= 0) { continue; } var comments = string.IsNullOrEmpty(errorMessage) ? null : string.Format("ERROR: {0}", errorMessage); string error; try { if (workflowInstanceTaskStatusID != (short)WorkflowInstanceTaskStatusEnum.Error) { if (!database.UpdateTaskStatus(task.WorkflowInstanceTaskID, workflowInstanceTaskStatusID, UserEmail, comments, out error)) { // Something horrible happened so stop the workflow... error = string.Format("Update Workflow Task Status[ WorkflowInstanceTaskID={0}, Status={1}, UserEmail={2} ] ERROR --> {3}", task.WorkflowInstanceTaskID, workflowInstanceTaskStatusID, UserEmail, error); trace.AppendLine(error); database.UpdateTaskStatusFailover(task.WorkflowInstanceTaskID, error, UserID); } } else { if (!database.RaiseException(task.WorkflowInstanceTaskID, UserEmail, comments, out error)) { // Something horrible happened so stop the workflow... error = string.Format("Update Workflow Task Status[ WorkflowInstanceTaskID={0}, Status={1}, UserEmail={2} ] ERROR --> {3}", task.WorkflowInstanceTaskID, workflowInstanceTaskStatusID, UserEmail, error); trace.AppendLine(error); database.UpdateTaskStatusFailover(task.WorkflowInstanceTaskID, error, UserID); } } } catch (Exception ex) { trace.AppendLine(ex.Message); database.UpdateTaskStatusFailover(task.WorkflowInstanceTaskID, ex.Message, UserID); } } } // This will be added to the service trace table TraceInfo = trace.ToString(); } #endregion } }