Example #1
0
        //仅处理open计算逻辑
        private void OpenWorkItem(List <WorkItem> others, WorkItem current)
        {
            HumanSetting setting = current.GetReferredSetting();

            if (!setting.IsUsingSlot)
            {
                current.ChangeStatus(WorkItemStatus.Open);
                return;
            }

            //已占用的slot数量
            var opened = others.Count(o =>
                                      o.Status == WorkItemStatus.Open || o.Status == WorkItemStatus.Executed);

            //slot占用完后将其他状态为New任务置为NoSlot
            if (opened + 1 >= setting.SlotCount)
            {
                others.ForEach(o =>
                {
                    if (o.Status != WorkItemStatus.New)
                    {
                        return;
                    }
                    o.ChangeStatus(WorkItemStatus.NoSlot);
                    _repository.Update(o);
                });
            }
            //没有slot可占用
            if (opened >= setting.SlotCount)
            {
                throw new InvalidOperationException(_no_task);
            }

            current.ChangeStatus(WorkItemStatus.Open);
        }
Example #2
0
        void IWorkItemService.Execute(long workItemId, User user, string action, IDictionary <string, string> inputs)
        {
            //HACK:open和execute放在同一事务内 避免两次updlock造成死锁

            //lock
            var all     = _repository.FindWorkItemsByActivityInstance(this.GetWorkItem(workItemId, user));
            var others  = all.Where(o => o.ID != workItemId).ToList();
            var current = all.FirstOrDefault(o => o.ID == workItemId);

            HumanSetting setting = current.GetReferredSetting();

            //允许执行不存在的action,用以支持一些隐含的动态规则,如:动态节点功能
            //if (!setting.Actions.Contains(action))
            //    throw new InvalidOperationException(string.Format("不存在名为“{0}”的Action定义", action));

            //open
            this.OpenWorkItem(others, current);

            //人工节点执行结果
            var result = string.Empty;
            var script = string.Empty;
            //人工节点是否完成
            var isHumanDone = false;

            #region 1.更新流程变量
            if (inputs != null && inputs.Count > 0)
            {
                current.Process.UpdateDataFields(inputs);
                this._processService.Update(current.Process);
            }
            #endregion

            #region 2.测试完成规则
            //所有其他的任务
            var allOtherExecutions = others
                                     .Select(o => new DefaultHumanFinishRuleAsserter.Execution(o.Result, o.Status))
                                     .ToList();
            //补充未创建的任务
            var nexts = current.ActivityInstance.GetNextUsers(setting.SlotCount, setting.IsUsingSlot);
            if (nexts.Count() > 0)
            {
                foreach (var u in nexts)
                {
                    allOtherExecutions.Add(new DefaultHumanFinishRuleAsserter.Execution(null, WorkItemStatus.New));
                }

                if (this._log.IsDebugEnabled)
                {
                    this._log.DebugFormat("由于存在未创建的任务,为任务判断而临时生成用户{0}的任务执行信息", string.Join("|", nexts));
                }
            }
            else if (setting.IsUsingSlot &&
                     setting.SlotMode == HumanSetting.SlotDistributionMode.OneAtOnce &&
                     allOtherExecutions.Count < current.ActivityInstance.Actioners.Length &&
                     this._log.IsDebugEnabled)
            {
                this._log.DebugFormat("由于Slot={0}均已被占用,剩余未被创建的用户{1}的任务将被忽略"
                                      , setting.SlotCount
                                      , string.Join("|", current.ActivityInstance.GetUsersWhoNotReady()));
            }
            //下一个未激活的任务
            var next    = current.ActivityInstance.GetNextUser(setting.SlotCount, setting.IsUsingSlot);
            var hasNext = !string.IsNullOrWhiteSpace(next);
            //所有其他任务是否已执行
            var allOtherExecuted = !hasNext &&
                                   allOtherExecutions.FirstOrDefault(o =>
                                                                     o.Status == WorkItemStatus.New || o.Status == WorkItemStatus.Open) == null;
            //没有完成规则的情况或其他任务都完成则完成
            //即使没有完成规则成立,只要其他任务都完成则节点完成
            if (allOtherExecuted)
            {
                isHumanDone = true;
            }
            //有规则的情况
            if (setting.FinishRule != null)
            {
                foreach (var s in setting.FinishRule.Scripts)
                {
                    //HACK:测试完成规则是否满足,遇到第一个满足的条件则退出
                    if (DependencyResolver.Resolve <IScriptParser>().EvaluateFinishRule(current
                                                                                        , allOtherExecutions
                                                                                        , current.Process.GetDataFields()
                                                                                        , action
                                                                                        , s.Value))
                    {
                        isHumanDone = true;
                        result      = s.Key;
                        script      = s.Value;
                        break;
                    }
                }
            }
            #endregion

            #region 3.更新任务状态
            current.MarkAsExecuted(action);
            _repository.Update(current);
            //若节点完成,撤销其他未执行的任务
            if (isHumanDone)
            {
                others.ForEach(o =>
                {
                    if (o.Status == WorkItemStatus.New || o.Status == WorkItemStatus.Open)
                    {
                        o.ChangeStatus(WorkItemStatus.Canceled);
                        _repository.Update(o);
                    }
                });
            }
            #endregion

            #region 4.若任务所在的人工环节完成
            if (isHumanDone)
            {
                //取消所有的未执行的 EscalationJobResumption
                this._resumptionService.CancelAllEscalationJob(current.Process, current.ActivityInstance.ID, current.ActivityName);
                //将人工节点实例置为完成
                current.ActivityInstance.SetAsComplete();
                this._processService.UpdateActivityInstance(current.ActivityInstance);
                //将流程置为运行状态
                current.Process.ChangeStatus(ProcessStatus.Running);
                this._processService.Update(current.Process);
                //并创建恢复请求
                this._resumptionService.Add(new BookmarkResumption(current.Process
                                                                   , current.ActivityInstance.ActivityName
                                                                   , current.ActivityInstance.ReferredBookmarkName
                                                                   , result));

                //HACK:节点完成事件
                this._bus.RaiseHumanActivityInstanceCompleted(new ActivityInstanceArgs(current.ActivityInstance, current.Process));
            }
            else if (hasNext)
            {
                //将流程置为运行状态
                current.Process.ChangeStatus(ProcessStatus.Running);
                this._processService.Update(current.Process);
                //HACK:创建下一个任务
                this._resumptionService.Add(new WorkItemCreateResumption(current.Process, current.ActivityInstance));
            }
            #endregion

            this._log.InfoFormat(
                "用户{0}执行节点“{1}”的任务#{2},Action={3}{4}{5}"
                , user.UserName
                , current.ActivityName
                , current.ID
                , action
                , isHumanDone ? ",满足人工节点完成条件“" + script + "”,将进入“" + result + "”" : ""
                , !isHumanDone && hasNext ? ",根据Slot分发规则OneAtOnce将为下一个用户" + next + "创建任务" : "");
        }