为什么我的CRM工作流程会触发无限循环保护?

时间:2012-05-15 11:55:24

标签: dynamics-crm dynamics-crm-2011 infinite-loop

更新

我应该从一开始就添加 - 这是在Microsoft Dynamics CRM 2011


我很了解CRM,但我无法解释当前部署的行为。

请阅读我的情景大纲,以帮助我理解我的哪些假设/理解是错误的(因此导致此错误的原因)。这与我的期望不符。

基本场景

  • 要求每X分钟调用一次Web服务(它将待处理的项添加到数据库索引中)
  • 我选择使用工作流程/自定义实体触发器模型(即我有一个自定义实体,其中注册了一个CREATE插件。该插件执行我的逻辑。当“完成”时间+时,启动随附的工作流程[超时期限] 到期。到期时,它会创建一个新的触发记录,工作流程结束)。
  • 插件逻辑工作得很好。工作流概念可以正常工作,但经过一段时间后,工作流失败了:

      

    此工作流作业已取消,因为启动它的工作流包含无限循环。更正工作流逻辑,然后重试。有关工作流逻辑的信息,请参阅“帮助”。

  •   
  简而言之 - 标准的无限循环检测。我理解这个概念及其存在的原因。

特定部署

首先,我认为在这种情况下忽略插件代码的内容是非常安全的。它工作正常,它是原子的,几乎不接触CRM(很明显,它是一个运行远程Web服务的事件前插件,等待响应,然后在我的Trigger记录上设置“完成日期”日期/时间属性,然后通过目标实体回到管道中)。只要创建了一个Trigger记录,该代码就会运行并执行它应有的操作。

打了插件的内容后,可能会有一个问题,我不赞成在实体的预创建步骤中注册插件...

这样就离开了工作流程本身。这是一个简单的。它如此运行:

  1. 创建新的触发器实体...
  2. 它有一个Trigger.new_completedon超时时间+ 15分钟
  3. on timeout,它会创建一个新的Trigger记录(没有“completed on”值 - 这是由插件设置记住的)
  4. 这就是全部 - 没有明确的“结束工作流程”(虽然我现在只添加了一个并将其设置为测试...)
  5. 通过这个设置,我手动创建一个新的Trigger记录,并且该过程可以很好地实现。向前滚动1小时58分钟(基于我运行的最后一个循环 - 记住我的插件代码可能需要一分钟才能完成运行),经过7个成功的执行周期(即创建并完成新的工作流程作业)后,第8个失败了上述错误。

    我已经知道的事情(纠正我错在哪里)

    Recursion depth, by default, is set to 8。如果工作流/插件自身调用8次,则会检测到无限循环。

    Recursion depth is reset every one houror 10 minutes - see "Warnings" in linked blog?)

    仅在内部部署中使用Recursion depth settings can be set via PowerShell

    Deployment Web Service或SDK代码via the Set-CrmSetting Cmdlet

    我不想听(请)

    “更改递归深度设置”

    我无法更改部署递归深度设置,因为这不是在线方案中的选项 - 最终我也将部署到CRM Online。

    延长工作流程的超时时间

    这也不是一个选项 - 重新索引需要每15分钟发生一次,理想情况下更快。

    更新

    @Boone建议在60分钟不活动之后重置递归深度超时,而不是每60分钟重置一次。这就是第一个误解。

    在与@alex讨论时,我建议在通过工作流创建实体和生成最终产生的工作流之间可能存在一些持久性的CorrelationId ......好吧。插件和工作流中的CorrelationId相同,并且该线程的任何记录都是相同的。我现在正在研究如何将CorrelationId(或者创建记录)与实体和工作流分离。

2 个答案:

答案 0 :(得分:3)

我怀疑这可以解决这个问题。

我建议采用不同的方法:在CRM旁边部署一个简单的应用程序,让 it 调用Web服务,然后可以使用XRM端点来更改记录。

<强>更新

或者,你可以在插件中的crm服务初始化(从我的一个插件中挖出来)尝试这样的事情,让你的工作流程不受影响:

CrmService service = new CrmService();
//initialize service here, then...

CorrelationToken newtoken = new CorrelationToken();
newtoken.CorrelationId = context.CorrelationId;
newtoken.CorrelationUpdatedTime = context.CorrelationUpdatedTime;

// WILD GUESS: Enforce unlimited depth ?
corToken.Depth = 0; // THIS WAS: context.Depth;

//updating correlation token
service.CorrelationTokenValue = corToken;

我承认我对此并不记得太多(代码可以追溯到大约2年前),但它可能有所帮助。

答案 1 :(得分:3)

要进行一小时“重置”,您必须在一小时内没有活动。它不会从原来只有1小时重置。因此,由于您每15分钟进行一次活动,因此无法重置。我不知道在任何地方都说是石头......但是根据我的经验。

在CRM 4中,可以创建CRM服务(Google creating a CRM service in the child pipeline)并重置相关ID(使用CorrelationToken.NewToken())。我在2011 SDK中看不到任何这么简单的事情。不知道这个技巧是否适用于在线环境。 2011在线向后兼容CRM 4插件吗?

您可以尝试的一件事是使用IExecutionContext.CorrelationId来清除异步(System Job)表。但是根据元数据,我认为可能有用的属性(CorrelationId,CorrelationUpdatedTime,Depth)对更新无效。 也许你可以删除行吗?即便如此也可能无济于事。