//仅处理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); }
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 + "创建任务" : ""); }