public ScheduledItem ProcessScheduledItem(string scheduleId, bool forceRun, out Activity activity) { activity = null; using (INodeProcessorMutex mutex = GetMutex(scheduleId)) { if (!mutex.IsAcquired) { LOG.Debug("Exiting ProcessScheduleItem(), could not acquire mutex"); return(null); // Another thread is already working on this transaction, get out of here } bool isRunNow; ScheduledItem scheduledItem = ScheduleManager.GetScheduledItem(scheduleId, out isRunNow); /*************************************/ var isDebugging = DebugUtils.IsDebugging; var computerPrefix = "COMPUTER: "; var allowScheduleToRun = !isDebugging; var hasComputerPrefix = scheduledItem.Name.StartsWith(computerPrefix, StringComparison.OrdinalIgnoreCase); if (hasComputerPrefix) { var specialPrefix = computerPrefix + Environment.MachineName; var hasSpecialPrefix = scheduledItem.Name.StartsWith(specialPrefix, StringComparison.OrdinalIgnoreCase); allowScheduleToRun = hasSpecialPrefix; } if (!allowScheduleToRun) { return(null); } /*************************************/ DateTime startTime = DateTime.Now; // Make sure the transaction has not been processed yet if (!forceRun && ((scheduledItem.NextRunOn > startTime) && !isRunNow)) { LOG.Debug("Exiting ProcessScheduledItem(), schedule {0} has already run", scheduledItem); return(null); } string flowName = _flowManager.GetDataFlowNameById(scheduledItem.FlowId); activity = new Activity(NodeMethod.Schedule, flowName, scheduledItem.Name, ActivityType.Info, null, NetworkUtils.GetLocalIp(), "Start processing schedule: \"{0}\"", scheduledItem.Name); string transactionId = null; try { // Make sure the user that created the schedule is still active UserAccount userAccount = _accountManager.GetById(scheduledItem.ModifiedById); if ((userAccount == null) || !userAccount.IsActive) { activity.AppendFormat("The user account that created the scheduled item \"{0}\" is no longer active. Scheduled item cannot execute.", scheduledItem.Name); return(null); } activity.ModifiedById = userAccount.Id; scheduledItem.ExecuteStatus = ScheduleExecuteStatus.Running; ScheduleManager.UpdateScheduleStatus(scheduledItem.Id, scheduledItem.ExecuteStatus); transactionId = _transactionManager.CreateTransaction(NodeMethod.Schedule, EndpointVersionType.Undefined, scheduledItem.FlowId, scheduledItem.Name, userAccount.Id, CommonTransactionStatusCode.Processing, null, null, null, false); activity.TransactionId = transactionId; SchedulePostProcessingAction postProcessingAction = SchedulePostProcessingAction.ContinueNormally; switch (scheduledItem.SourceType) { case ScheduledItemSourceType.LocalService: postProcessingAction = ProcessLocalServiceSource(scheduledItem, activity, transactionId); break; case ScheduledItemSourceType.File: ProcessFileSource(scheduledItem, activity, transactionId); break; case ScheduledItemSourceType.WebServiceQuery: ProcessWebServiceQuerySource(scheduledItem, activity, transactionId); break; case ScheduledItemSourceType.WebServiceSolicit: ProcessWebServiceSolicitSource(scheduledItem, activity, transactionId); break; default: throw new ArgumentException(string.Format("Unrecognized scheduledItem.SourceType: {0}", scheduledItem.SourceType)); } TransactionStatus transactionStatus = null; if (postProcessingAction != SchedulePostProcessingAction.None) { if (scheduledItem.TargetType != ScheduledItemTargetType.None) { transactionStatus = _transactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Processed, null, false); switch (scheduledItem.TargetType) { case ScheduledItemTargetType.LocalService: ProcessLocalServiceTarget(transactionStatus, scheduledItem, activity); break; case ScheduledItemTargetType.Email: ProcessEmailTarget(transactionStatus, scheduledItem, activity); break; case ScheduledItemTargetType.File: ProcessFileTarget(transactionStatus, scheduledItem, activity); break; case ScheduledItemTargetType.Partner: ProcessPartnerTarget(transactionStatus, scheduledItem, activity); break; case ScheduledItemTargetType.Schematron: ProcessSchematronTarget(transactionStatus, scheduledItem, activity); break; default: throw new ArgumentException(string.Format("Unrecognized scheduledItem.TargetType: {0}", scheduledItem.TargetType)); } } } transactionStatus = _transactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Completed, null, true); activity.AppendFormat("End processing schedule: \"{0}\", processing duration: {1}", scheduledItem.Name, TimeSpan.FromTicks(DateTime.Now.Ticks - startTime.Ticks).ToString()); activity.AppendFormat("Transaction \"{0}\" status set to \"{1}\"", transactionStatus.Id.ToString(), transactionStatus.Status.ToString()); _notificationManager.DoScheduleNotifications(transactionStatus, scheduledItem.FlowId, scheduledItem.Name); scheduledItem.ExecuteStatus = ScheduleExecuteStatus.CompletedSuccess; } catch (Exception e) { activity.Type = ActivityType.Error; TransactionStatus transactionStatus = null; if (transactionId != null) { transactionStatus = _transactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Failed, e.Message, true); activity.AppendFormat("Transaction \"{0}\" status set to \"{1}\"", transactionStatus.Id.ToString(), transactionStatus.Status.ToString()); } LogActivityError(activity, ExceptionUtils.ToShortString(e)); LOG.Error("ProcessTransactionRequest() threw an exception.", e); if (transactionId != null) { _notificationManager.DoScheduleNotifications(transactionStatus, scheduledItem.FlowId, scheduledItem.Name, "Error: " + ExceptionUtils.GetDeepExceptionMessageOnly(e)); } scheduledItem.ExecuteStatus = ScheduleExecuteStatus.CompletedFailure; } finally { ActivityManager.Log(activity); UpdateScheduleRunInfo(scheduledItem, activity); } return(scheduledItem); } }
protected void ProcessSubmitTransaction(string transactionId) { using (INodeProcessorMutex mutex = GetMutex(transactionId)) { if (!mutex.IsAcquired) { LOG.Debug("Exiting ProcessTransactionRequest(), could not acquire mutex for transaction {0}", transactionId); return; // Another thread is already working on this transaction, get out of here } // Make sure the transaction has not been processed yet string transactionModifiedBy; if (!TransactionManager.IsUnprocessed(transactionId, out transactionModifiedBy)) { LOG.Debug("Exiting ProcessSubmitTransaction(), transaction {0} has already been processed", transactionId); return; } DateTime startTime = DateTime.Now; Activity activity = new Activity(NodeMethod.Submit, null, null, ActivityType.Info, transactionId, NetworkUtils.GetLocalIp(), "Start processing submit transaction: \"{0}\"", transactionId); activity.ModifiedById = transactionModifiedBy; try { TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Pending, "Processing submit transaction", false); // Get the document processing service string flowName, operation; DataService submitService = TransactionManager.GetSubmitDocumentServiceForTransaction(transactionId, out flowName, out operation); if (submitService == null) { if (!string.IsNullOrEmpty(operation)) { throw new ArgumentException(string.Format("A valid Submit service was not found for the flow \"{0}\" and operation \"{1}\"", flowName, operation)); } // Let empty operation pass through, even without a valid service, per Mark } else if (!submitService.IsActive) { throw new ArgumentException(string.Format("The Submit service is not active for the flow \"{0}\" and operation \"{1}\"", flowName, operation)); } if (submitService == null) { activity.Append("No service found for Submit transaction"); TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, CommonTransactionStatusCode.ReceivedUnprocessed, "Received unprocessed submit transaction", CommonTransactionStatusCode.Received, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); } else { CommonTransactionStatusCode submitTransactionStatus = CommonTransactionStatusCode.Processed; string submitTransactionStatusDetail = "Finished processing submit transaction"; ISubmitProcessor submitProcessor; using (IPluginDisposer disposer = PluginLoader.LoadSubmitProcessor(submitService, out submitProcessor)) { TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Processing, "Processing submit transaction", true); activity.Append("Set transaction status to Processing"); activity.AppendFormat("Processing Submit transaction for flow \"{0}\" and operation \"{1}\" using plugin \"{2}\"", flowName, operation, submitProcessor.GetType().FullName); try { ISubmitProcessorEx submitProcessorEx = submitProcessor as ISubmitProcessorEx; if (submitProcessorEx != null) { submitTransactionStatus = submitProcessorEx.ProcessSubmitAndReturnStatus(transactionId, out submitTransactionStatusDetail); activity.AppendFormat("Submit processing plugin returned status of \"{0}\"", submitTransactionStatus.ToString()); } else { submitProcessor.ProcessSubmit(transactionId); } } finally { activity.Append(submitProcessor.GetAuditLogEvents()); } TimeSpan processLength = DateTime.Now - startTime; activity.AppendFormat("Process time: {0}", processLength.ToString()); } activity.Append("Finished processing submit transaction"); TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, submitTransactionStatus, submitTransactionStatusDetail, CommonTransactionStatusCode.Received | CommonTransactionStatusCode.Completed | CommonTransactionStatusCode.Failed, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); activity.AppendFormat(TransactionManager.DoTransactionNotifications(transactionId)); } } catch (Exception e) { LOG.Error("ProcessSubmitTransaction() threw an exception.", e); TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, CommonTransactionStatusCode.Failed, e.Message, CommonTransactionStatusCode.Received, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); activity.Append(ExceptionUtils.ToShortString(e)); activity.Type = ActivityType.Error; activity.AppendFormat(TransactionManager.DoTransactionNotifications(transactionId)); } finally { ActivityManager.Log(activity); } } }
protected void ProcessSolicitTransaction(string transactionId) { using (INodeProcessorMutex mutex = GetMutex(transactionId)) { if (!mutex.IsAcquired) { LOG.Debug("Exiting ProcessSolicitTransaction(), could not acquire mutex"); return; // Another thread is already working on this transaction, get out of here } // Make sure the transaction has not been processed yet string transactionModifiedBy; if (!TransactionManager.IsUnprocessed(transactionId, out transactionModifiedBy)) { LOG.Debug("Exiting ProcessSolicitTransaction(), transaction {0} has already been processed", transactionId); return; } Activity activity = new Activity(NodeMethod.Solicit, null, null, ActivityType.Info, transactionId, NetworkUtils.GetLocalIp(), "Start processing solicit transaction: \"{0}\"", transactionId); activity.ModifiedById = transactionModifiedBy; try { TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Pending, "Processing solicit transaction", false); // Get the request processing service string requestId, flowName, operation; DataService solicitService = TransactionManager.GetSolicitServiceForTransaction(transactionId, out flowName, out operation, out requestId); if ((solicitService == null) || !solicitService.IsActive) { throw new ArgumentException(string.Format("A valid solicit service was not found for the transaction \"{0}\"", transactionId)); } TimeSpan processLength; ISolicitProcessor plugin; using (IPluginDisposer disposer = PluginLoader.LoadSolicitProcessor(solicitService, out plugin)) { TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Processing, string.Format("Processing request with transaction id \"{0}\"", transactionId), true); DateTime startTime = DateTime.Now; activity.Append("Set transaction status to Processing"); activity.AppendFormat("Processing Solicit transaction for flow \"{0}\" and operation \"{1}\" using plugin \"{2}\"", flowName, operation, plugin.GetType().FullName); try { plugin.ProcessSolicit(requestId); } finally { activity.Append(plugin.GetAuditLogEvents()); } processLength = DateTime.Now - startTime; } activity.AppendFormat("Process time: {0}", processLength.ToString()); TransactionStatus transactionStatus = TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Completed, string.Format("Completed solicit request with transaction id \"{0}\"", transactionId), true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); activity.AppendFormat(TransactionManager.DoTransactionNotifications(transactionId)); } catch (Exception e) { TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, CommonTransactionStatusCode.Failed, e.Message, CommonTransactionStatusCode.Received, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); activity.Append(ExceptionUtils.ToShortString(e)); activity.Type = ActivityType.Error; activity.AppendFormat(TransactionManager.DoTransactionNotifications(transactionId)); LOG.Error("ProcessSolicitTransaction() threw an exception.", e); } finally { ActivityManager.Log(activity); } } }
protected void ProcessNotifyTransaction(string transactionId) { using (INodeProcessorMutex mutex = GetMutex(transactionId)) { if (!mutex.IsAcquired) { LOG.Debug("Exiting ProcessNotifyTransaction(), could not acquire mutex"); return; // Another thread is already working on this transaction, get out of here } // Make sure the transaction has not been processed yet string transactionModifiedBy; if (!TransactionManager.IsUnprocessed(transactionId, out transactionModifiedBy)) { if (!TransactionManager.IsUnprocessed(transactionId)) { LOG.Debug("Exiting ProcessNotifyTransaction(), transaction {0} has already been processed", transactionId); return; } } Activity activity = new Activity(NodeMethod.Notify, null, null, ActivityType.Info, transactionId, NetworkUtils.GetLocalIp(), "Start processing notify transaction: \"{0}\"", transactionId); activity.ModifiedById = transactionModifiedBy; try { TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Pending, "Processing notify transaction", false); // Get the document processing service // TODO: No documentService means failure? string flowName, operation; DataService notifyService = TransactionManager.GetNotifyDocumentServiceForTransaction(transactionId, out flowName, out operation); if (notifyService == null) { // Let notify pass through, even without a valid service, per Mark } else if (!notifyService.IsActive) { throw new ArgumentException(string.Format("The Notify service is not active for the flow \"{0}\"", flowName)); } if (notifyService == null) { activity.Append("No service found for Notify transaction"); TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, CommonTransactionStatusCode.ReceivedUnprocessed, "Received unprocessed notify transaction", CommonTransactionStatusCode.Received, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); } else { INotifyProcessor plugin; using (IPluginDisposer disposer = PluginLoader.LoadNotifyProcessor(notifyService, out plugin)) { TransactionManager.SetTransactionStatus(transactionId, CommonTransactionStatusCode.Processing, "Processing notify transaction", true); activity.Append("Set transaction status to Processing"); DateTime startTime = DateTime.Now; activity.AppendFormat("Processing Notify transaction for flow \"{0}\" and operation \"{1}\" using plugin \"{2}\"", flowName, operation, plugin.GetType().FullName); try { plugin.ProcessNotify(transactionId); } finally { activity.Append(plugin.GetAuditLogEvents()); } TimeSpan processLength = DateTime.Now - startTime; activity.AppendFormat("Process time: {0}", processLength.ToString()); } activity.Append("Finished processing notify transaction"); TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, CommonTransactionStatusCode.Processed, "Finished processing notify transaction", CommonTransactionStatusCode.Received, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); } } catch (Exception e) { TransactionStatus transactionStatus = TransactionManager.SetTransactionStatusIfNotStatus(transactionId, CommonTransactionStatusCode.Failed, e.Message, CommonTransactionStatusCode.Received, true); activity.AppendFormat("Transaction status set to \"{0}\"", transactionStatus.Status.ToString()); activity.Append(ExceptionUtils.ToShortString(e)); activity.Type = ActivityType.Error; LOG.Error("ProcessNotifyTransaction() threw an exception.", e); } finally { ActivityManager.Log(activity); } } }