예제 #1
0
        public string ResumeWorkflowAsync_new(WorkflowRun workflowRun, IWorkflowEvent resumeEvent)
        {
            Factory.WorkflowRunTaskManager.RegisterStart(workflowRun.TaskId);

            bool runInForeground = WorkflowRunContext.Current.RunTriggersInCurrentThread;

            var queueEvent = resumeEvent as IWorkflowQueuedEvent;

            if (queueEvent == null)
            {
                EventLog.Application.WriteError("Attempted to queue a resume task that cannot be queued, running it on the foreground thread instead. EventType: {resumeEvent.GetType()}");
                runInForeground = true;
            }

            if (runInForeground)
            {
                ResumeWorkflow(workflowRun, resumeEvent);
            }
            else
            {
                var task = ResumeWorkflowHandler.CreateBackgroundTask(workflowRun, queueEvent);

                Factory.BackgroundTaskManager.EnqueueTask(task);

                HandleDiagnostics(workflowRun, "Queued");
            }

            return(workflowRun.TaskId);
        }
        public void SuspendRestore()
        {
            using (new SecurityBypassContext())
            {
                var handler = new ResumeWorkflowHandler();

                var run = new WorkflowRun()
                {
                    WorkflowRunStatus_Enum = WorkflowRunState_Enumeration.WorkflowRunSuspended
                };
                run.Save();

                var task = ResumeWorkflowHandler.CreateBackgroundTask(run, new WorkflowRestoreEvent());

                var taskEntity = handler.CreateSuspendedTask(task).As <SuspendedRun>();
                taskEntity.Save();

                taskEntity.Should().NotBeNull();
                taskEntity.SrRun.Should().NotBeNull();
                taskEntity.SrRun.Id.Should().Be(run.Id);

                var bgTasks = handler.RestoreSuspendedTasks();

                bgTasks.Should().HaveCount(1);

                var runParam = bgTasks.First().GetData <ResumeWorkflowParams>();

                runParam.WorkflowRunId.ShouldBeEquivalentTo(run.Id);
                Assert.That(runParam.WorkflowRunId, Is.EqualTo(run.Id));
            }
        }
예제 #3
0
        /// <summary>
        /// Resume any suspended runs, putting them back on the queue.
        /// Note that this does not deal with the queue already containing suspended runs.
        /// </summary>
        public static void ResumeSuspendedRuns()
        {
            var suspendedIds = Entity.GetCalculationMatchesAsIds("Status='Long running'", WorkflowRun.WorkflowRun_Type, false);

            if (suspendedIds.Any())
            {
                var runs = Entity.Get <WorkflowRun>(suspendedIds);

                foreach (var run in runs)
                {
                    var restoreTask = ResumeWorkflowHandler.CreateBackgroundTask(run, new WorkflowRestoreEvent());
                    Factory.BackgroundTaskManager.EnqueueTask(restoreTask);
                }
            }
        }
예제 #4
0
        void ActionOnTask_new(long runId, UserCompletesTaskEvent resumeEvent, bool runInThread)
        {
            BackgroundTask bgTask;

            using (new SecurityBypassContext())
            {
                var run = Entity.Get <WorkflowRun>(runId);                       // If we don't do this we get caching problems
                var wf  = run.WorkflowBeingRun;

                bgTask = ResumeWorkflowHandler.CreateBackgroundTask(run, resumeEvent);
            }

            if (runInThread)
            {
                Factory.BackgroundTaskManager.ExecuteImmediately(bgTask);
            }
            else
            {
                Factory.BackgroundTaskManager.EnqueueTask(bgTask);
            }
        }
예제 #5
0
        private WorkflowRun FinalizeRun(IRunState runState)
        {
            WorkflowRun run;

            using (Profiler.Measure("WorkflowRunner.Instance.FinalizeRun"))
            {
                using (new SecurityBypassContext())
                {
                    try
                    {
                        run = runState.WorkflowRun;
                        runState.CompletedAt = DateTime.UtcNow;
                        if (!run.IsTemporaryId)
                        {
                            run = Entity.Get <WorkflowRun>(runState.WorkflowRun,
                                                           true,
                                                           WorkflowRun.WorkflowRunExitPoint_Field,
                                                           WorkflowRun.HasTimeout_Field,
                                                           WorkflowRun.PendingActivity_Field,
                                                           WorkflowRun.RunStepCounter_Field,
                                                           WorkflowRun.WorkflowRunStatus_Field,
                                                           WorkflowRun.RunCompletedAt_Field,
                                                           WorkflowRun.StateInfo_Field);
                        }

                        var deferredRun = run as WorkflowRunDeferred;
                        if (deferredRun != null)
                        {
                            deferredRun.Sync();
                        }



                        runState.SyncToRun(run);

                        WorkflowRunContext.Current.DeferSave(run);

                        //
                        // Raise a completed child event
                        //
                        if (run != null && run.ParentRun != null && IsRunCompleted(run))
                        {
                            // This should be hooked into an eventing system. As we don't have one, just run the resume async.
                            runState.WorkflowInvoker.PostEvent(new ChildWorkflowCompletedEvent(run));
                        }

                        //
                        // Add a restore message to the queue if we are suspended
                        //
                        if (run != null && run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunSuspended)
                        {
                            WorkflowRunContext.Current.DeferAction(() =>
                            {
                                // This should be hooked into an eventing system. As we don't have one, just run the resume async.
                                var restoreTask = ResumeWorkflowHandler.CreateBackgroundTask(run, new WorkflowRestoreEvent());
                                Factory.BackgroundTaskManager.EnqueueTask(restoreTask);
                            });
                        }


                        //
                        // Let the world know we have finished
                        WorkflowRunContext.Current.DeferAction(() =>
                        {
                            if (run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunPaused ||
                                run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunCompleted ||
                                run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunFailed)
                            {
                                Factory.WorkflowRunTaskManager.RegisterComplete(run.TaskId, run.Id.ToString(CultureInfo.InvariantCulture));
                            }
                            else
                            {
                                Factory.WorkflowRunTaskManager.SetResult(run.TaskId, run.Id.ToString(CultureInfo.InvariantCulture));
                            }
                            HandleDiagnostics(run, run.WorkflowRunStatus_Enum.ToString());
                        });
                    }
                    catch (Exception ex)
                    {
                        Workflow workflow = runState != null?Entity.Get <Workflow>(runState.WorkflowRunId) : null;

                        var msg = string.Format("Workflow: {0}. Unexpected error when finalizing the workflow run ({1}), version ({2}).",
                                                runState != null ? runState.GetSafeWorkflowDescription() : "",
                                                runState != null ? runState.WorkflowRunId : -1L,
                                                workflow != null ? workflow.WorkflowVersion : 0);

                        var log = msg + Environment.NewLine + ex.Message;

#if DEBUG
                        log += Environment.NewLine + ex.StackTrace;
#endif

                        EventLog.Application.WriteError(log);

                        throw new Exception(msg, ex);
                    }
                }
            }

            return(run);
        }