private static void WriteBackAbortMessage(WorkflowHandlerBase stateContent, WorkflowApplicationAbortReason reason) { try { var abortMessage = GetAbortMessage(reason, stateContent); if (reason == WorkflowApplicationAbortReason.StateContentDeleted) { var msg = "Workflow aborted. Reason: " + abortMessage + "."; if (stateContent != null) { msg += " InstanceId: " + stateContent.WorkflowInstanceGuid; } Debug.WriteLine("##WF> " + msg); Logger.WriteInformation(Logger.EventId.NotDefined, msg); } else { WriteBackAbortMessage(stateContent, abortMessage); } } catch (Exception e) { WriteError("WriteBackAbortMessage#1", e); throw; } }
public static void ExecuteDelays(WorkflowHandlerBase workflowInstance) { //var abortedList = new List<Guid>(); //var doneList = new List<Guid>(); //while (true) //{ // var wfApp = CreateWorkflowApplication(workflowInstance, WorkflowApplicationCreationPurpose.Poll, null); // try // { // wfApp.LoadRunnableInstance(TimeSpan.FromSeconds(1)); // if (doneList.Contains(wfApp.Id)) // { // wfApp.Cancel(); // WriteBackAbortMessage(workflowInstance, "Cannot execute the workflow twice in the same period. The workflow may contain a corrupt operation (e.g. state or related content modification)."); // } // else // { // if (ValidWakedUpWorkflow(wfApp)) // { // wfApp.Run(); // doneList.Add(wfApp.Id); // } // else // { // if (!abortedList.Contains(wfApp.Id)) // { // abortedList.Add(wfApp.Id); // wfApp.Cancel(); // } // } // } // } // catch (InstanceNotReadyException) // { // break; // } //} try { var wfApps = LoadRunnableInstances(workflowInstance); foreach (var wfApp in wfApps) { if (ValidWakedUpWorkflow(wfApp)) { wfApp.Run(); } else { wfApp.Cancel(); } } } catch (Exception e) { WriteError("ExecuteDelays", e); throw; } }
private static string GetAbortMessage(WorkflowApplicationAbortReason reason, WorkflowHandlerBase workflow) { try { switch (reason) { case WorkflowApplicationAbortReason.ManuallyAborted: return(String.Concat(ABORTEDBYUSERMESSAGE, AccessProvider.Current.GetCurrentUser().Username)); case WorkflowApplicationAbortReason.StateContentDeleted: return("Workflow deleted" + (workflow == null ? "." : (": " + workflow.Path))); case WorkflowApplicationAbortReason.RelatedContentChanged: return("Aborted because the related content was changed."); case WorkflowApplicationAbortReason.RelatedContentDeleted: return("Aborted because the related content was moved or deleted."); default: return(reason.ToString()); } } catch (Exception e) { WriteError("GetAbortMessage", e); throw; } }
private static IEnumerable <WorkflowApplication> LoadRunnableInstances(WorkflowHandlerBase workflowInstance) { try { var wfApps = new List <WorkflowApplication>(); while (true) { try { var wfApp = CreateWorkflowApplication(workflowInstance, WorkflowApplicationCreationPurpose.Poll, null); wfApp.LoadRunnableInstance(); wfApps.Add(wfApp); } catch (InstanceNotReadyException) { break; } } var loadedInstanceIds = wfApps.Select(w => w.Id).ToArray(); WriteDebug("<#> Loaded instances: (" + loadedInstanceIds.Length + "): " + String.Join(", ", loadedInstanceIds)); return(wfApps); } catch (Exception e) { WriteError("LoadRunnableInstances", e); throw; } }
private static SqlWorkflowInstanceStore CreateInstanceStore(WorkflowHandlerBase workflowInstance, out InstanceHandle ownerHandle) { try { //WriteDebug("CreateInstanceStore: " + workflowInstance.WorkflowInstanceGuid + ", nodeId: " + workflowInstance.Id); var store = new SqlWorkflowInstanceStore(ConnectionString); ownerHandle = store.CreateInstanceHandle(); var wfHostTypeName = GetWorkflowHostTypeName(workflowInstance); var WorkflowHostTypePropertyName = GetWorkflowHostTypePropertyName(); var ownerCommand = new CreateWorkflowOwnerCommand() { InstanceOwnerMetadata = { { WorkflowHostTypePropertyName, new InstanceValue(wfHostTypeName) } } }; var owner = store.Execute(ownerHandle, ownerCommand, TimeSpan.FromSeconds(30)).InstanceOwner; ownerHandle.Free(); store.DefaultInstanceOwner = owner; return(store); } catch (Exception e) { WriteError("CreateInstanceStore", e); throw; } }
private static WorkflowApplication CreateWorkflowApplication(WorkflowHandlerBase workflowInstance, WorkflowApplicationCreationPurpose purpose, IDictionary <string, object> parameters) { try { string version; WorkflowApplication wfApp = null; var workflow = workflowInstance.CreateWorkflowInstance(out version); switch (purpose) { case WorkflowApplicationCreationPurpose.StartNew: Dictionary <string, object> arguments = workflowInstance.CreateParameters(); arguments.Add(STATECONTENT, new WfContent(workflowInstance)); if (parameters != null) { foreach (var item in parameters) { arguments.Add(item.Key, item.Value); } } wfApp = new WorkflowApplication(workflow, arguments); workflowInstance.WorkflowDefinitionVersion = version; workflowInstance.WorkflowInstanceGuid = wfApp.Id.ToString(); break; default: wfApp = new WorkflowApplication(workflow); break; } WriteDebug("CreateWorkflowApplication: NodeId: " + workflowInstance.Id + ", instanceId: " + workflowInstance.WorkflowInstanceGuid + ", Purpose: " + purpose); InstanceHandle ownerHandle; var store = CreateInstanceStore(workflowInstance, out ownerHandle); Dictionary <XName, object> wfScope = new Dictionary <XName, object> { { GetWorkflowHostTypePropertyName(), GetWorkflowHostTypeName(workflowInstance) } }; wfApp.InstanceStore = store; wfApp.AddInitialInstanceValues(wfScope); wfApp.PersistableIdle = a => { WriteDebug("PersistableIdle " + wfApp.Id); DestroyInstanceOwner(wfApp, ownerHandle); return(PersistableIdleAction.Unload); }; wfApp.Unloaded = b => { WriteDebug("Unloaded " + wfApp.Id); DestroyInstanceOwner(wfApp, ownerHandle); }; wfApp.Completed = c => { WriteDebug("Completed " + wfApp.Id); OnWorkflowCompleted(c); DestroyInstanceOwner(wfApp, ownerHandle); }; wfApp.Aborted = d => { WriteDebug("Aborted " + wfApp.Id); OnWorkflowAborted(d); DestroyInstanceOwner(wfApp, ownerHandle); }; wfApp.OnUnhandledException = e => { WriteDebug("OnUnhandledException " + wfApp.Id); return(HandleError(e)); }; wfApp.Extensions.Add(new ContentWorkflowExtension() { WorkflowInstancePath = workflowInstance.Path }); return(wfApp); } catch (Exception e) { WriteError("CreateWorkflowApplication", e); throw; } }
private static void WriteBackAbortMessage(WorkflowHandlerBase stateContent, string abortMessage) { try { var state = stateContent.WorkflowStatus; if (state == WorkflowStatusEnum.Completed) { return; } // if a system message has already been persisted to the workflow content, don't overwrite it if (!string.IsNullOrEmpty(stateContent.SystemMessages)) { return; } var times = 3; while (true) { try { stateContent.SystemMessages = abortMessage; stateContent.DisableObserver(typeof(WorkflowNotificationObserver)); Debug.WriteLine("##WF> Workflow aborted. Reason: " + abortMessage + ". InstanceId: " + stateContent.WorkflowInstanceGuid); using (new SystemAccount()) stateContent.Save(ContentRepository.SavingMode.KeepVersion); break; } catch (NodeIsOutOfDateException ne) { if (--times == 0) { throw new NodeIsOutOfDateException("Node is out of date after 3 trying", ne); } var msg = "InstanceManager: Saving system message caused NodeIsOutOfDateException. Trying again."; Logger.WriteVerbose(msg); Debug.WriteLine("##WF> ERROR " + msg); stateContent = (WorkflowHandlerBase)Node.LoadNodeByVersionId(stateContent.VersionId); } catch (Exception e) { var msg = String.Format("InstanceManager: Cannot write back a system message to the workflow state content. InstanceId: {0}. Path: {1}. Message: {2}. InstanceId: {3}." , stateContent.Id, stateContent.Path, abortMessage, stateContent.WorkflowInstanceGuid); Debug.WriteLine("##WF> ERROR " + msg); Logger.WriteWarning(Logger.EventId.NotDefined, msg, properties: new Dictionary <string, object> { { "Exception", e } }); break; } } } catch (Exception e) { WriteError("WriteBackAbortMessage#2", e); throw; } }
//=========================================================================================================== Operations public static Guid Start(WorkflowHandlerBase workflowInstance) { try { var wfApp = CreateWorkflowApplication(workflowInstance, WorkflowApplicationCreationPurpose.StartNew, null); var id = wfApp.Id; workflowInstance.WorkflowStatus = WorkflowStatusEnum.Running; workflowInstance.DisableObserver(typeof(WorkflowNotificationObserver)); using (new SystemAccount()) workflowInstance.Save(); wfApp.Run(); return(id); } catch (Exception e) { WriteError("Start", e); throw; } }
private static WorkflowHandlerBase GetStateContent(WorkflowApplicationUnhandledExceptionEventArgs args) { try { WorkflowHandlerBase stateContent = null; var exts = args.GetInstanceExtensions <ContentWorkflowExtension>(); if (exts != null) { var ext = exts.FirstOrDefault(); if (ext != null) { stateContent = Node.Load <WorkflowHandlerBase>(ext.WorkflowInstancePath); } } return(stateContent); } catch (Exception e) { WriteError("GetStateContent#1", e); throw; } }
private static UnhandledExceptionAction HandleError(WorkflowApplicationUnhandledExceptionEventArgs args) { try { Logger.WriteException(args.UnhandledException); WorkflowHandlerBase stateContent = GetStateContent(args); if (stateContent == null) { Logger.WriteWarning(Logger.EventId.NotDefined, "The workflow InstanceManager cannot write back the aborting/terminating reason into the workflow state content."); } else { WriteBackAbortMessage(stateContent, DumpException(args)); } } catch (Exception e) { Debug.WriteLine("##WF> OnUnhandledException: " + e.ToString().Replace("\r\n", "<br/>").Replace("\r", "<br/>").Replace("\n", "<br/>")); Logger.WriteException(e); } return(UnhandledExceptionAction.Abort); }
public static void Abort(WorkflowHandlerBase workflowInstance, WorkflowApplicationAbortReason reason) { try { //check permissions if (reason == WorkflowApplicationAbortReason.ManuallyAborted && !workflowInstance.Security.HasPermission(PermissionType.Save)) { Logger.WriteVerbose(String.Concat("InstanceManager cannot abort the instance: ", workflowInstance.Path, ", because the user doesn't have the sufficient permissions (Save).")); throw new SecurityException(workflowInstance.Path, PermissionType.Save, AccessProvider.Current.GetCurrentUser()); } //abort the workflow var name = workflowInstance == null ? "[null]" : workflowInstance.Name; try { var wfApp = CreateWorkflowApplication(workflowInstance, WorkflowApplicationCreationPurpose.Abort, null); wfApp.Load(Guid.Parse(workflowInstance.WorkflowInstanceGuid)); //wfApp.Abort(); wfApp.Cancel(); //.Terminate(string.Format("#### Aborted. Reason {0}, Path: {1}", reason, workflowInstance.Path)); } catch (Exception e) { WriteDebug("================ CANNOT ABORT: " + name); Logger.WriteVerbose(String.Concat("InstanceManager cannot abort the instance: ", workflowInstance.Path, ". Exception message: ", e.Message)); } //write back workflow state WriteBackAbortMessage(workflowInstance, reason); } catch (Exception e) { WriteError("Abort", e); throw; } }
private void StartWorkflow(WorkflowHandlerBase wfTemplate, Node currentNode) { var list = (ContentList)currentNode.LoadContentList(); var targetFolder = list.GetWorkflowContainer(); // Node.LoadNode(targetFolderPath); var wfInstance = (WorkflowHandlerBase)ContentTemplate.CreateTemplated(targetFolder, wfTemplate, wfTemplate.Name).ContentHandler; wfInstance.RelatedContent = currentNode; if (!ValidateWorkflow(wfInstance, currentNode)) { wfInstance.Save(); return; } wfInstance["OwnerSiteUrl"] = PortalContext.Current.RequestedUri.GetLeftPart(UriPartial.Authority); using (new SystemAccount()) { //We need to save the wf instance before the engine starts it to have everything persisted to the repo. //Please do not remove this line. wfInstance.Save(); } InstanceManager.Start(wfInstance); }
private static XName GetWorkflowHostTypeName(WorkflowHandlerBase workflowInstance) { return(XName.Get(workflowInstance.WorkflowHostType, "http://www.com/2010/workflow")); }
protected virtual bool ValidateWorkflow(WorkflowHandlerBase wfContent, Node currentNode) { return(true); }