Пример #1
0
 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;
     }
 }
Пример #2
0
        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;
            }
        }
Пример #3
0
        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;
            }
        }
Пример #4
0
        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;
            }
        }
Пример #5
0
        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;
            }
        }
Пример #6
0
        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;
            }
        }
Пример #7
0
        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;
            }
        }
Пример #8
0
        //=========================================================================================================== 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;
            }
        }
Пример #9
0
 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;
     }
 }
Пример #10
0
        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);
        }
Пример #11
0
        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;
            }
        }
Пример #12
0
        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);
        }
Пример #13
0
 private static XName GetWorkflowHostTypeName(WorkflowHandlerBase workflowInstance)
 {
     return(XName.Get(workflowInstance.WorkflowHostType, "http://www.com/2010/workflow"));
 }
Пример #14
0
 protected virtual bool ValidateWorkflow(WorkflowHandlerBase wfContent, Node currentNode)
 {
     return(true);
 }