Example #1
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r        = waitingResumption as ProcessStartResumption;
            var instance = WorkflowBuilder.CreateInstance(r.Process, this._parser);

            instance.Run();
        }
Example #2
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r   = waitingResumption as SubProcessCreateResumption;
            var sub = r.SubProcessActivityInstance;

            if (sub == null)
            {
                this._log.Warn("不存在待创建子流程的子流程节点信息");
                return;
            }

            var parent  = r.Process;
            var setting = parent.ProcessType.GetSubProcessSetting(sub.ActivityName);

            if (setting == null)
            {
                throw new InvalidOperationException(string.Format(
                                                        "没有找到节点“{0}”对应的SubProcessSetting,可能需要修正流程"
                                                        , sub.ActivityName));
            }
            //更新子流程节点实例
            var subProcessId = Guid.NewGuid();

            sub.SetSubProcessId(subProcessId);
            this._processService.UpdateActivityInstance(sub);
            //创建子流程
            this._subHelper.Create(parent, setting.SubProcessTypeName, subProcessId);
        }
Example #3
0
        //HACK:【重要】对单个流程实例的串行顺序调度(不包含仍处于延迟期的调度?),有异常则跳出

        /*
         * 关于父子流程之间的调度顺序影响问题解决
         * 在按流程串行调度前提下,按调度影响点分析
         * 1.发起子流程:无影响
         * 2.子流程结束:子流程本身正常结束即可,对父流程的唤醒排入父流程调度项序列中,按父流程的行为继续调度即可,对应SubProcessCompleteResumption设计
         * 3.并行活动中取消子流程节点:
         *      ActivityInstanceCancelResumption节点取消调度被设计为可自动重试,
         *      直到子流程处于调度项安全状态时才会被删除
         */
        internal void Resume(IOrderedEnumerable <long> list)
        {
            bool error = false;
            WaitingResumption prev = null, r = null;

            foreach (var id in list.Distinct())
            {
                r = this._resumptionService.Get(id);
                //忽略不存在的调度项
                if (r == null)
                {
                    continue;
                }

                if (error &&
                    !this.AreAtSameFlowNodeIndex(prev, r))
                {
                    this._log.WarnFormat("对流程“{0}”#{1}进行串行调度时异常,中断本次对该流程的调度,等待自动或人工重试"
                                         , r.Process != null ? r.Process.Title : string.Empty
                                         , r.Process != null ? r.Process.ID : Guid.Empty);
                    return;
                }

                error = !this.Resume(id);
                prev  = r;
            }
        }
Example #4
0
 protected virtual void MakeAnError(WaitingResumption r, Exception e)
 {
     //HACK:【重要】此处必须保证更新被提交,不能被nhsession问题影响,因此必须直接sqlupdate来保证
     //r.SetError(true);
     //this._resumptionService.Update(r);
     this._resumptionService.MarkAsError(r);
     this._resumptionService.AddErrorRecord(new FaultResumptionRecord(r.Process, e, r.ID));
 }
Example #5
0
 private bool AreAtSameFlowNodeIndex(WaitingResumption prev, WaitingResumption r)
 {
     return(!prev.FlowNodeIndex.HasValue ||
            !r.FlowNodeIndex.HasValue ||
            (prev.FlowNodeIndex.HasValue &&
             r.FlowNodeIndex.HasValue &&
             r.FlowNodeIndex == prev.FlowNodeIndex));
 }
Example #6
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r            = waitingResumption as HumanEscalationResumption;
            var process      = r.Process;
            var activityName = r.HumanActivityInstance.ActivityName;
            var setting      = process.ProcessType.GetHumanSetting(activityName);
            var workItems    = this._workItemService.GetWorkItems(process, activityName);
            HumanEscalationRule          rule       = setting.EscalationRule;
            IDictionary <string, string> dataFields = process.GetDataFields();

            if (rule == null ||
                !rule.IsValid ||
                workItems.Count() == 0)
            {
                this._log.WarnFormat("流程“{0}”#{1}的节点“{2}”的超时事件升级规则无效或已经失效"
                                     , process.Title
                                     , process.ID
                                     , r.HumanActivityInstance.ActivityName);
                return;
            }
            string to;

            if (rule.NotifyTemplateName != null)
            {
                //消息通知
                this._helper.Notify(process, workItems, rule.NotifyTemplateName);
                //重复通知
                if (rule.NotifyRepeatMinutes.HasValue)
                {
                    //从当前开始计算
                    var at = DateTime.Now.AddMinutes(rule.NotifyRepeatMinutes.Value);
                    this._schedulerService.Add(new HumanEscalationResumption(r.Process, at, r.HumanActivityInstance));
                    this._log.InfoFormat("由于设置了重复通知,再次创建超时事件升级调度项,将于{0}激活", at);
                }
            }
            else if (!string.IsNullOrEmpty(rule.RedirectTo)
                     //HACK:【脚本使用】解析脚本获取实际转交目标
                     && !string.IsNullOrWhiteSpace(to = this.Evaluate(rule.RedirectTo, process)))
            {
                //将当前任务转交给其他人
                this._helper.Redirect(process, activityName, workItems, to);
            }
            else if (!string.IsNullOrEmpty(rule.GotoActivityName))
            {
                //强制跳转到指定节点
                this._helper.Goto(process, activityName, rule.GotoActivityName);
            }
        }
Example #7
0
 private void TrySetAsActiveAtResumption(Process process, WaitingResumption resumption)
 {
     //只有部分调度项完成后才可进入Active
     if (!resumption.EnableActiveAfterExecuted)
     {
         return;
     }
     //HACK:【重要】只要存在未执行的有效调度项就不可进入Active状态
     if (this._resumptionService.AnyValidAndUnExecutedResumptions(process, resumption))
     {
         this._log.InfoFormat("由于流程存在未完成的调度请求,无法将其置为Active状态");
         return;
     }
     process.MarkAsActive();
     this._processService.Update(process);
     this._log.InfoFormat("流程实例“{0}”#{1}进入Active状态", process.Title, process.ID);
 }
Example #8
0
        public virtual void Resume(WaitingResumption r)
        {
            //HACK:【重要】时间调度有可能导致调度器被未满足请求占满,必须在repository层ChargeResumption时预先进行过滤
            if (!r.CanResumeAtNow)
            {
                if (this._log.IsDebugEnabled)
                {
                    this._log.Debug("当前时间未满足延迟调度项的时间条件");
                }
                return;
            }

            /*
             * HACK:【重要】将处于不可执行的调度项置为无效,用于处理由于以下原因出现的不合法的调度记录:
             * 流程状态与调度状态发生冲突,不过此类情况已经在调度重构后最大限度避免,但由于调度/服务分离的方式,还是保留此逻辑避免意外
             */
            if (!r.CanExecuting)
            {
                r.SetInvalid();
                this._resumptionService.Update(r);
                this._log.WarnFormat("流程{0}#{1}处于{2}状态,该调度请求不允许被执行,取消该调度请求{3}#{4}"
                                     , r.Process.Title
                                     , r.Process.ID
                                     , r.Process.Status
                                     , r
                                     , r.ID);
                return;
            }
            //通过调度项对应的执行器执行实际调度逻辑
            DependencyResolver.Resolve <IWaitingResumptionHandle>(r.Handle).Resume(r);
            //尝试将流程置为Active状态
            this.TrySetAsActiveAtResumption(r.Process, r);//注意与Update(r)的先后顺序,避免二者逻辑(update与AnyValidAndUnExecutedResumptions)死锁
            //置为已执行
            r.SetExecuted();
            this._resumptionService.Update(r);

            this._log.InfoFormat(
                "[调度记录]{0}#{1}|Priority={2}|ProcessTitle={3}|ProcessId={4}"
                , r
                , r.ID
                , r.Priority
                , r.Process.Title
                , r.Process.ID);
        }
Example #9
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r         = waitingResumption as BookmarkResumption;
            var persisted = this._processService.GetWorkflowInstance(r.Process).WorkflowInstance;
            var instance  = WorkflowBuilder.CreateInstance(r.Process, this._parser);

            instance.Load(persisted);

            //只能尝试恢复存在的书签
            if (instance.GetBookmarks().Any(o => o.Name == r.BookmarkName))
            {
                instance.Update(r.Process.GetInputs());
                instance.ResumeBookmark(r.BookmarkName, r.Value);
            }
            else
            {
                this._log.WarnFormat("没有在流程“{0}”#{1}中找到名为{2}的书签,取消本次恢复", r.Process.Title, r.Process.ID, r.BookmarkName);
            }
        }
Example #10
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r             = waitingResumption as SubProcessCompleteResumption;
            var subProcess    = r.SubProcess;
            var parentProcess = r.Process;

            //尝试从父流程中获取启动该子流程的节点实例信息
            SubProcessActivityInstance sub = this._processService.GetSubProcessActivityInstances(parentProcess, subProcess);

            if (sub == null)
            {
                throw new InvalidOperationException(string.Format("没有在父流程“{0}”#{1}中找到启动子流程“{2}”#{3}的子流程节点实例"
                                                                  , parentProcess.Title
                                                                  , parentProcess.ID
                                                                  , subProcess.Title
                                                                  , subProcess.ID));
            }
            //将子流程的流程变量传递给父流程
            var dict = subProcess.GetDataFields();

            foreach (string key in dict.Keys)
            {
                parentProcess.UpdateDataField(key, dict[key]);
            }
            //唤醒父流程
            var persisted = this._processService.GetWorkflowInstance(parentProcess).WorkflowInstance;
            var instance  = WorkflowBuilder.CreateInstance(parentProcess, this._parser);

            instance.Load(persisted);
            instance.Update(parentProcess.GetInputs());
            instance.ResumeBookmark(sub.ReferredBookmarkName, null);
            //目前不允许在调度项中生成新的非延迟调度项,无法保证预期顺序,需要有类似核心的quack机制
            ////创建父流程唤醒调度项
            //this._resumption.Add(new BookmarkResumption(parentProcess
            //    , sub.ActivityName
            //    , sub.ReferredBookmarkName
            //    , string.Empty));

            //将子流程节点置为完成
            sub.SetAsComplete();
            this._processService.UpdateActivityInstance(sub);
        }
Example #11
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r = waitingResumption as ActivityInstanceCancelResumption;

            try
            {
                //由于该调度项是允许自动重试的,应避免无关异常产生影响调度队列
                if (r != null &&
                    r.Process != null &&
                    r.ActivityInstance != null)
                {
                    this._processService.CancelAllAbout(r.Process, r.ActivityInstance);
                }
            }
            catch (Exception e)
            {
                this._log.Warn("取消流程节点实例时异常,将自动重试", e);
                throw e;
            }
        }
Example #12
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            try
            {
                var r = waitingResumption as ErrorResumption;
                //错误恢复使用粗粒度实现,不延续原有工作流实例树
                var instance = WorkflowBuilder.CreateInstance(r.Process, this._parser);
                instance.Update(r.Process.GetInputs());
                instance.Run();

                this._log.InfoFormat("尝试对流程{0}#{1}在FlowNodeIndex={2}处进行了错误恢复"
                                     , r.Process.Title
                                     , r.Process.ID
                                     , r.ErrorNodeIndex);
            }
            catch (Exception e)
            {
                //由于ErrorResumption本身就是错误恢复调度,即使异常也不应抛出而导致其本身被记录成error
                this._log.Error("错误重试时异常", e);
            }
        }
Example #13
0
        void IWaitingResumptionHandle.Resume(WaitingResumption waitingResumption)
        {
            var r     = waitingResumption as WorkItemCreateResumption;
            var human = r.HumanActivityInstance;

            if (human == null)
            {
                this._log.Warn("不存在待创建任务的人工节点信息");
                return;
            }

            var process = r.Process;
            var setting = process.ProcessType.GetHumanSetting(human.ActivityName);

            if (setting == null)
            {
                throw new InvalidOperationException("没有找到节点"
                                                    + human.ActivityName
                                                    + "对应的HumanSetting,可能需要修正流程");
            }

            //OneAtOnce依次创建
            if (setting.SlotMode == HumanSetting.SlotDistributionMode.OneAtOnce)
            {
                this._workItemService.Create(human.CreateNextWorkItem(process, this._userService));
            }
            else
            {
                //AllAtOnce一次性创建
                var list = human.CreateAllWorkItem(process, this._userService);
                foreach (var w in list)
                {
                    this._workItemService.Create(w);
                }
            }
            //更新节点实例
            this._processService.UpdateActivityInstance(human);
        }
Example #14
0
 bool ISchedulerService.AnyValidAndUnExecutedResumptions(Process process, WaitingResumption except)
 {
     return _resumptionRepository.FindAnyValidAndUnExecutedResumptions(process, except);
 }
Example #15
0
        void ISchedulerService.MarkAsError(WaitingResumption r)
        {
            r.SetError(true);
            _resumptionRepository.SetError(r, true);

        }
Example #16
0
 void ISchedulerService.Update(WaitingResumption r)
 {
     _resumptionRepository.Update(r);
 }
Example #17
0
 void ISchedulerService.Add(WaitingResumption r)
 {
     _resumptionRepository.Add(r);
 }