跳到主要内容

Workflow Patterns 评估

查看 Markdown

Workflow Patterns 是一组业务流程中反复出现的行为。它们由 Workflow Patterns Initiative 定义,由 Wil van der Aalst 和 Arthur ter Hofstede 主导。研究者用它们比较 BPMN、BPEL、YAWL 等 workflow 语言和引擎。每个模式都有 ID、名称和精确定义。定义见 control-flow patterns。

本页按 43 个 control-flow 模式(WCP-1 到 WCP-43)为 Dex 评级。data、resource 和 exception-handling 模式不在本页评估范围内。

评级标准​

评级沿用已发表评估的标准。

  • + 表示直接支持。一个 Dex 构件就满足定义的每一部分,应用无需为它保存额外状态。
  • +/- 表示间接支持。Dex 通过组合几个构件来实现该模式,例如 Channel 信号、Attribute 计数、锁、RPC 检查或重复等待的循环。少数几行中,定义的某一部分以受限形式成立,该行会写明是哪一部分。已发表的评估把这一档称为 partial support。
  • - 表示不支持。

Dex 构件是编程模型的一部分:Primitive、Step decision、等待条件,或者五个 SDK 都提供、并在文档中作为标准写法的 SDK API。Join 就是这样的 API。

Dex 如何汇合并行分支​

Join 在一个 Flow 内汇合并行分支。它建在 ChannelMap 之上,五个 SDK 都提供。

  • 拆分 Step 用 Fork 开启一轮。Fork 在同一个 decision 里启动所有分支和一个汇合 Step,并把同一个 round token 交给它们。
  • token 里有 round key 和分支数。round key 来自开启这一轮的 Step 执行,所以应用不用保存计数器,也不用保存 key。
  • 每个分支结束时上报一个结果。
  • 汇合 Step 等待全部分支、第一个分支或其中 n 个分支。它的等待是普通的条件,可以和 Timer 组合。
  • 一轮的结果永远不会计入另一轮。
  • 汇合在所有分支上报之前就触发时,下一轮的拆分 Step 会先等完上一轮剩下的结果。这就是复位,不需要额外的 Step。

当工作在子 Flow 中运行时,用 AllOf 等待 SubFlow 就是原生的汇合。

有 10 个模式仍是 +/-,原因如下:

  • WCP-15 和 WCP-36 在其他实例运行时继续添加实例。Join 在 fork 时就需要知道分支数,所以这两个示例都不用 Join。WCP-15 在锁的保护下保存启动计数和关闭添加的标志,汇合 Step 每收到一个结果就重新等待。WCP-36 保存一个关闭准入的标志、一个记录已启动投标的 AttributeMap 和一把锁,汇合 Step 每收到一个结果就重新等待,直到条件成立。
  • WCP-33 为每个输入分支分别排队触发,并把多余的触发留给以后。Join 按轮次计数,不按分支排队。
  • WCP-38 要从流程结构判断已经不可能有线程再到达合并点。这是可达性问题,不是计数问题。
  • WCP-17 和 WCP-40 依赖 Attribute lock,而锁只覆盖一个 Execute。
  • WCP-18、WCP-20、WCP-23 和 WCP-39 不是汇合,所以 Join 不改变它们的评级。评级原因见各自的那一行。

Join 的限制​

Join 计数的是分支上报的结果,它不观察分支 Step 本身。由此有以下限制。

  • 每个分支每轮必须恰好上报一次,所有退出路径都要上报,包括失败路由去往的 Step。从不上报的分支会让等待全部分支的汇合一直等下去。上报两次的分支会被计两次。
  • 从外部取消的分支(例如被 RPC 取消)不会上报。等待全部分支的汇合会一直等下去。要把汇合和分支一起取消,或者用 AnyOf 同时等待汇合和一个 Timer。
  • 从外部取消分支这一点不影响评级。在 Petri net 和 YAWL 中,取消同步区域内的任务同样会让 AND-join 死锁,除非取消区域包含这个 join。
  • 带取消的汇合,它的那一轮永远不复位。被取消的分支不会上报,所以等待其余结果的复位永远等不完。在循环中,下一轮直接 fork 新的一轮,round key 会把它和旧的一轮分开。
  • 汇合 Step 的等待已经消费了结果,但它的 Execute 结果还没保存时,它可能被取消。这些结果是否回到这一轮,取决于 server 版本,见被取消的 Step 与已消费的消息。如果结果丢失,为同一轮重新建立的汇合永远不会触发。

评级如何验证​

每个模式都有 TypeScript、Python、Go、Java 和 Rust 五种语言的可运行示例。每个示例都有针对真实 Dex Server 的集成测试,测试断言该模式的定义行为。例如,Deferred Choice 的测试同时发送两个相互竞争的响应,并检查恰好只有一个分支运行。

汇总​

  • 33 个模式直接支持(+)。
  • 10 个模式间接支持(+/-)。
  • 没有不支持(-)的模式。

与已发表评估的比较​

一项已发表的评估按同样的 43 个 control-flow 模式评估了六个 workflow 和 BPM 系统。作者是 Wohed、Russell、ter Hofstede、Andersson 和 van der Aalst,发表于 Information and Software Technology 51(8),2009(PDF)。在其 Table 20 中,每个系统直接支持 11 到 20 个模式,部分支持最多 6 个,有 19 到 32 个模式不支持。Dex 没有不支持的模式。

结果​

表中列出每个评级依据的 Dex 构件。

Pattern评级Dex 构件示例
WCP-1 Sequence+GoToTS · Python · Go · Java · Rust
WCP-2 Parallel Split+GoToManyTS · Python · Go · Java · Rust
WCP-3 Synchronization+Join:Fork 启动各分支和汇合 Step;汇合 Step 等待 ForAllBranchesTS · Python · Go · Java · Rust
WCP-4 Exclusive Choice+Execute 返回指向一个 Step 的 GoToTS · Python · Go · Java · Rust
WCP-5 Simple Merge+多个 Step GoTo 同一个 Step typeTS · Python · Go · Java · Rust
WCP-6 Multi-Choice+GoToMany 只启动选中的 StepTS · Python · Go · Java · Rust
WCP-7 Structured Synchronizing Merge+Join:做选择的 Step 只 fork 选中的分支;汇合 Step 等待 ForAllBranchesTS · Python · Go · Java · Rust
WCP-8 Multi-Merge+每个分支都 GoTo 同一个 Step type;每次到达都再运行一次TS · Python · Go · Java · Rust
WCP-9 Structured Discriminator+Join 等待 1 个分支(ForBranches);下一轮的拆分 Step 用 ForRemainingBranches 复位TS · Python · Go · Java · Rust
WCP-10 Arbitrary Cycles+GoTo 任意 Step;循环有两个入口和两个出口TS · Python · Go · Java · Rust
WCP-11 Implicit Termination+GracefulComplete 在没有活动 Step 时才关闭 FlowTS · Python · Go · Java · Rust
WCP-12 Multiple Instances without Synchronization+GoToMany 启动同一 Step type 的多个执行;没有 Step 等待它们TS · Python · Go · Java · Rust
WCP-13 Multiple Instances with a priori Design-Time Knowledge+Join fork 固定数量的实例;汇合 Step 等待 ForAllBranchesTS · Python · Go · Java · Rust
WCP-14 Multiple Instances with a priori Run-Time Knowledge+Join 为每个输入项 fork 一个实例;汇合 Step 等待 ForAllBranchesTS · Python · Go · Java · Rust
WCP-15 Multiple Instances without a priori Run-Time Knowledge+/-RPC 添加执行;Attribute 计数;汇合 Step 循环等待TS · Python · Go · Java · Rust
WCP-16 Deferred Choice+对多个 Channel 使用 AnyOf;只消费被选中的消息,所以只运行一个分支TS · Python · Go · Java · Rust
WCP-17 Interleaved Parallel Routing+/-各任务的 Execute 共用 Attribute lock;它只覆盖一个 ExecuteTS · Python · Go · Java · Rust
WCP-18 Milestone+/-Attribute 标记状态;RPC 只在该状态下启动任务TS · Python · Go · Java · Rust
WCP-19 Cancel Task+RPC 结果取消一个 Step type,并启动下一个 StepTS · Python · Go · Java · Rust
WCP-20 Cancel Case+/-启动 SubFlow 的 Step 同时等待取消 Channel,停止子 Flow,再返回 ForceFailTS · Python · Go · Java · Rust
WCP-21 Structured Loop+前置判断 Step GoTo 循环体或出口TS · Python · Go · Java · Rust
WCP-22 Recursion+Step 等待同一 Flow type 的 SubFlowTS · Python · Go · Java · Rust
WCP-23 Transient Trigger+/-共享 Attribute lock 下的 RPC 检查只在有 Step 等待时接受一次触发TS · Python · Go · Java · Rust
WCP-24 Persistent Trigger+Channel 消息一直排队,直到 Step 消费TS · Python · Go · Java · Rust
WCP-25 Cancel Region+RPC 结果一次取消多个 Step typeTS · Python · Go · Java · Rust
WCP-26 Cancel Multiple Instance Activity+RPC 结果取消实例的 Step type;已完成的实例保留结果TS · Python · Go · Java · Rust
WCP-27 Complete Multiple Instance Activity+RPC 结果取消实例和汇合 Step,再启动下一个 StepTS · Python · Go · Java · Rust
WCP-28 Blocking Discriminator+Join 等待 1 个分支(ForBranches);ForRemainingBranches 复位之后下一轮才开始TS · Python · Go · Java · Rust
WCP-29 Cancelling Discriminator+Join 等待 1 个分支(ForBranches);汇合 Step 的 decision 取消它的 sibling 分支TS · Python · Go · Java · Rust
WCP-30 Structured Partial Join+Join 等待 n 个分支(ForBranches);下一轮的拆分 Step 用 ForRemainingBranches 复位TS · Python · Go · Java · Rust
WCP-31 Blocking Partial Join+Join 等待 n 个分支(ForBranches);ForRemainingBranches 复位之后下一轮才开始TS · Python · Go · Java · Rust
WCP-32 Cancelling Partial Join+Join 等待 n 个分支(ForBranches);汇合 Step 的 decision 取消它的 sibling 分支TS · Python · Go · Java · Rust
WCP-33 Generalised AND-Join+/-对多个 Channel 使用 AllOf;多余信号留给下一次触发TS · Python · Go · Java · Rust
WCP-34 Static Partial Join for Multiple Instances+Join 在 m 个实例中等待 n 个(ForBranches);下一轮的拆分 Step 用 ForRemainingBranches 复位TS · Python · Go · Java · Rust
WCP-35 Cancelling Partial Join for Multiple Instances+Join 在 m 个实例中等待 n 个(ForBranches);汇合 Step 的 decision 取消它的 sibling 实例TS · Python · Go · Java · Rust
WCP-36 Dynamic Partial Join for Multiple Instances+/-RPC 添加实例;汇合 Step 循环等待并检查条件TS · Python · Go · Java · Rust
WCP-37 Local Synchronizing Merge+Join:分叉的 Step fork 活跃的分支;汇合 Step 等待 ForAllBranchesTS · Python · Go · Java · Rust
WCP-38 General Synchronizing Merge+/-Attribute 记录仍能到达汇合点的线程数;降到 0 时发布哨兵消息TS · Python · Go · Java · Rust
WCP-39 Critical Section+/-用只含一条消息的 Channel 充当令牌TS · Python · Go · Java · Rust
WCP-40 Interleaved Routing+/-各任务的 Execute 共用 Attribute lock,再用 ForN 汇合;锁只覆盖一个 ExecuteTS · Python · Go · Java · Rust
WCP-41 Thread Merge+Join 汇合同一 Step type 的多个线程;合并 Step 等待 ForAllBranchesTS · Python · Go · Java · Rust
WCP-42 Thread Split+GoToMany 启动同一 Step type 的多个执行TS · Python · Go · Java · Rust
WCP-43 Explicit Termination+ForceComplete 立即关闭 Flow,并取消其他 StepTS · Python · Go · Java · Rust

评级依据的行为​

评级依赖以下 Dex 行为。

  • GracefulComplete 只在没有活动 Step 时关闭 Flow。
  • DeadEnd 只结束一个分支,从不关闭 Flow。
  • ForceComplete 立即关闭 Flow,并取消其他 Step。
  • AnyOf 只消费被选中条件的消息。
  • Channel 消息一直排队,直到被 Step 消费。
  • decision 或 RPC 按 Step type 取消 Step。Dex 不会强行停止被取消方法的代码。方法会一直运行,直到它检查到取消并返回。
  • 同一时间只有一个 Step 方法或 RPC 持有某个 Attribute lock。
  • 父 Flow 关闭后,SubFlow 会继续运行。
  • Join 按开启一轮的 Step 执行区分各轮。一轮的结果永远不会满足另一轮的汇合。
  • Step 方法只在成功时发布消息,所以重试的分支只上报一次结果。
  • decision 可以只取消 sibling Step。sibling 是同一个 decision 一起启动的 Step。如果某一轮是 RPC 用显式 round key fork 的,这些分支是该 RPC 名称启动过的所有 Step 的 sibling,所以要按 Step type 显式取消。

这些概念见 Step、Channel 和 SubFlow。

各模式详情​

WCP-1 Sequence​

模式含义:一个任务只在它前面的任务完成后才开始。两个任务属于同一个流程。见官方定义。

Dex 实现:每个 Step 的 Execute 返回指向下一个 Step 的 GoTo。示例依次运行 ReceiveOrder、CheckInventory 和 ShipOrder。

评级:+。GoTo 就是顺序构件。

示例:TS · Python · Go · Java · Rust

WCP-2 Parallel Split​

模式含义:一个分支拆分成两个或更多分支。这些分支同时运行。见官方定义。

Dex 实现:Step 返回 GoToMany,每个分支一个 Step movement。示例把一个订单拆分为打包和付款。

评级:+。GoToMany 就是拆分构件。

示例:TS · Python · Go · Java · Rust

WCP-3 Synchronization​

模式含义:两个或更多分支汇合成一个。只有每个输入分支都完成后,后续分支才开始。见官方定义。

Dex 实现:拆分 Step 对一个 Join 调用 Fork。Fork 返回各分支和汇合 Step,供一个 GoToMany 使用,并给它们同一个 round token。每个分支以 EndBranch 结束,它会上报本分支的结果。汇合 Step 等待 ForAllBranches。

评级:+。Join 就是汇合构件。Fork 数出分支数并生成 round key,应用不用保存计数。

示例:TS · Python · Go · Java · Rust

WCP-4 Exclusive Choice​

模式含义:一个分支拆分成多个,但控制只传给其中一个。由一个条件决定传给哪个。见官方定义。

Dex 实现:Execute 计算条件,返回指向一个 Step 的 GoTo。示例按金额把理赔交给人工审核或自动批准。

评级:+。只含一个 GoTo 的 decision 就是选择构件。

示例:TS · Python · Go · Java · Rust

WCP-5 Simple Merge​

模式含义:两个或更多分支汇合成一个。每次到达都把控制传下去。该模式假设同一时间只有一个输入分支处于活动状态。见官方定义。

Dex 实现:每个分支都返回指向同一个 Step type 的 GoTo。示例中两个审核分支都进入 CloseClaim。

评级:+。共同的 GoTo 目标就是合并。

示例:TS · Python · Go · Java · Rust

WCP-6 Multi-Choice​

模式含义:一个分支拆分成多个。控制传给其中一个或多个,由条件选出这一组。见官方定义。

Dex 实现:Execute 列出被选中的 Step,并对它们返回 GoToMany。示例根据输入选择邮件、短信或推送通知。

评级:+。对计算出的列表使用 GoToMany 就是多选构件。

示例:TS · Python · Go · Java · Rust

WCP-7 Structured Synchronizing Merge​

模式含义:由前面一个 Multi-Choice 启动的分支汇合成一个。汇合只等待实际启动的分支。在结构化模型中,它对应唯一一个 Multi-Choice。见官方定义。

Dex 实现:做选择的 Step 只把选中的分支交给 Fork。每个分支以 EndBranch 结束。汇合 Step 等待 ForAllBranches,所以它等的正好是已启动的分支。

评级:+。分支数来自 Fork,应用不用把它传给汇合 Step。

示例:TS · Python · Go · Java · Rust

WCP-8 Multi-Merge​

模式含义:多个分支汇合成一个。每次到达都单独把控制传下去,后续任务每次到达运行一次。见官方定义。

Dex 实现:每个分支都返回指向同一个 Step type 的 GoTo。每次到达,Dex 都启动该 Step 的一个新执行。

评级:+。每个 GoTo 都创建自己的 Step 执行。

示例:TS · Python · Go · Java · Rust

WCP-9 Structured Discriminator​

模式含义:并行拆分之后,最先到达的分支把控制传下去,之后到达的分支不再传递。所有分支都到达后,该构件复位。见官方定义。

Dex 实现:拆分 Step 用 Join fork 每一轮。汇合 Step 等待 1 个分支(ForBranches),然后传递控制。它同时用 round token 启动下一轮的拆分 Step。这个 Step 的 WaitFor 等待 ForRemainingBranches,消费这一轮其余的结果,这就是复位。然后它 fork 下一轮。示例把被忽略的结果记在一个 Attribute 里。

评级:+。Join 按开启一轮的 Step 执行区分各轮,所以迟到的结果永远不会传递控制。复位不需要额外的 Step,也不需要轮次计数器。

示例:TS · Python · Go · Java · Rust

WCP-10 Arbitrary Cycles​

模式含义:流程中的循环可以有多个入口或出口。见官方定义。

Dex 实现:Step 之间可以任意 GoTo,包括已经运行过的 Step。示例中的起草和编辑循环有两个入口和两个出口。

评级:+。GoTo 可以指向任何 Step。

示例:TS · Python · Go · Java · Rust

WCP-11 Implicit Termination​

模式含义:当现在和将来都没有剩余工作时,流程结束,不需要专门的结束节点。见官方定义。

Dex 实现:每个完成的分支都返回 GracefulComplete。只有没有活动 Step 时,Flow 才关闭。

评级:+。GracefulComplete 会等待最后一个活动 Step。

示例:TS · Python · Go · Java · Rust

WCP-12 Multiple Instances without Synchronization​

模式含义:一个任务在同一个流程实例中以多个独立实例运行,没有任何东西等待它们完成。见官方定义。

Dex 实现:Step 返回 GoToMany,同一 Step type 每个实例一个执行。Flow 在另一个分支上继续,不需要汇合。

评级:+。GoToMany 启动这些实例,没有 Step 等待它们。

示例:TS · Python · Go · Java · Rust

WCP-13 Multiple Instances with a priori Design-Time Knowledge​

模式含义:实例数量在模型中固定。这些实例同时运行,全部完成后流程才继续。见官方定义。

Dex 实现:Step 用固定的实例列表 fork 一个 Join。每个实例以 EndBranch 结束。汇合 Step 等待 ForAllBranches。

评级:+。每个实例就是 Join 的一个分支,由 Fork 计数。

示例:TS · Python · Go · Java · Rust

WCP-14 Multiple Instances with a priori Run-Time Knowledge​

模式含义:实例数量在运行时、实例启动之前确定。这些实例同时运行,全部完成后流程才继续。见官方定义。

Dex 实现:Step 为输入中的每一项构造一个实例,并用这个列表 fork 一个 Join。汇合 Step 等待 ForAllBranches。

评级:+。实例数就是交给 Fork 的列表长度,应用不用保存计数。

示例:TS · Python · Go · Java · Rust

WCP-15 Multiple Instances without a priori Run-Time Knowledge​

模式含义:直到最后一个实例完成,实例数量才确定。其他实例运行时可以启动新实例。全部完成后流程才继续。见官方定义。

Dex 实现:RPC 通过 next Steps 启动每个新实例,并在 Attribute 中计数。另一个 RPC 停止添加新实例。汇合 Step 每次等待一个结果,一直循环,直到不能再添加新实例且每个实例都已报告。

评级:+/-。汇合由 RPC、Attribute 计数和每收到一个结果就重新等待的循环组合而成。

示例:TS · Python · Go · Java · Rust

WCP-16 Deferred Choice​

模式含义:由外部环境在分支之间做选择。在其中一个分支开始之前,每个分支都可能执行。之后其余分支被撤回。见官方定义。

Dex 实现:一个 Step 用 AnyOf 等待,每个分支一个 Channel。Dex 只消费被选中条件的消息。Execute 进入与之对应的分支。

评级:+。AnyOf 决定竞争结果,只有一个分支会开始。

设计模式:Deferred Choice。

示例:TS · Python · Go · Java · Rust

WCP-17 Interleaved Parallel Routing​

模式含义:一组任务按偏序允许的任意顺序运行。每个任务运行一次,任意两个任务都不同时运行。见官方定义。

Dex 实现:每个任务的 Execute 都在同一个 Attribute 上声明锁。GoTo 表示偏序。汇合 Step 用 ForN 等待各任务的信号。

评级:+/-。路由由锁和 Channel 信号组合而成。锁只覆盖一个 Execute,不覆盖 WaitFor,也不覆盖跨多个 Step 的任务。

示例:TS · Python · Go · Java · Rust

WCP-18 Milestone​

模式含义:只有流程处于某个状态时,任务才能开始。流程越过这个状态后,任务再也不能开始。见官方定义。

Dex 实现:Attribute 标记变更窗口已打开。RPC 只在该 Attribute 成立时通过 next Steps 启动任务。之后的 Step 清除它。

评级:+/-。Step 无法检查其他分支的状态,所以用 Attribute 和 RPC 检查代替。

示例:TS · Python · Go · Java · Rust

WCP-19 Cancel Task​

模式含义:已启用的任务在开始前被撤回;正在运行的任务尽可能被停止。见官方定义。

Dex 实现:RPC 结果按 Step type 取消正在等待的 Step,并启动另一个 Step。Dex 让这两项改动同时生效。

评级:+。取消 Step 是 RPC 结果的内置功能。

示例:TS · Python · Go · Java · Rust

WCP-20 Cancel Case​

模式含义:整个流程实例被移除,包括正在运行的任务、将来的任务和 "all sub-processes",并记为不成功。见官方定义。

Dex 实现:启动 SubFlow 的 Step 用 AnyOf 等待子 Flow 或一个取消 Channel。收到取消后,它用 SubFlow.getFlowId 读取子 Flow 的 ID,用 Client StopFlow 停止子 Flow,再返回 ForceFail。ForceFail 取消其他所有活动 Step。

评级:+/-。只用 Client StopFlow 会让正在运行的 SubFlow 继续运行,所以示例组合了取消 Channel、显式停止和 ForceFail。

设计模式:连同子 Flow 一起取消。

示例:TS · Python · Go · Java · Rust

WCP-21 Structured Loop​

模式含义:任务或子流程在条件成立时重复执行。条件在每次执行之前或之后检查。循环只有一个入口和一个出口。见官方定义。

Dex 实现:前置判断 Step GoTo 循环体或出口。循环体再 GoTo 前置判断。

评级:+。GoTo 构成循环。

示例:TS · Python · Go · Java · Rust

WCP-22 Recursion​

模式含义:任务可以直接或通过祖先调用自身。见官方定义。

Dex 实现:Step 等待同一 Flow type 的 SubFlow。示例用这种方式计算阶乘。

评级:+。SubFlow 可以运行与父 Flow 相同的 Flow type。

示例:TS · Python · Go · Java · Rust

WCP-23 Transient Trigger​

模式含义:信号只有在任务已经在等待时才能触发它。没有任务等待时到达的信号会丢失。见官方定义。

Dex 实现:Step 的 WaitFor 设置一个 Attribute,记录它正在等待。RPC 在该 Attribute 上声明锁,只在它已设置时接受触发,并在接受时清除它。之后的触发都会被丢弃。

评级:+/-。Channel 消息会持久保存,所以示例组合了 Attribute、锁和 RPC 检查来丢弃触发。

示例:TS · Python · Go · Java · Rust

WCP-24 Persistent Trigger​

模式含义:信号会被保留,直到某个任务能处理它。见官方定义。

Dex 实现:RPC 把信号发布到 Channel。消息一直排队,直到某个 Step 的 WaitFor 消费它。

评级:+。Channel 消息本来就会持久保存。

示例:TS · Python · Go · Java · Rust

WCP-25 Cancel Region​

模式含义:一组任务被一起撤回。这些任务不必相连。见官方定义。

Dex 实现:RPC 结果列出要取消的多个 Step type,并启动下一个 Step。其他 Step 继续运行。

评级:+。一个 RPC 结果就能取消任意一组 Step type。

示例:TS · Python · Go · Java · Rust

WCP-26 Cancel Multiple Instance Activity​

模式含义:多实例任务可以随时取消。未完成的实例被撤回,已完成的实例保留结果。见官方定义。

Dex 实现:RPC 结果取消实例的 Step type。已经完成的实例不受影响。

评级:+。按 Step type 取消会覆盖所有未完成的实例。

示例:TS · Python · Go · Java · Rust

WCP-27 Complete Multiple Instance Activity​

模式含义:多实例任务可以被强制完成。剩余实例被撤回,流程继续。见官方定义。

Dex 实现:RPC 结果取消各实例及其汇合 Step,然后用已有结果启动下一个 Step。

评级:+。一个 RPC 结果既取消各实例,又启动下一个 Step。

示例:TS · Python · Go · Java · Rust

WCP-28 Blocking Discriminator​

模式含义:最先到达的分支把控制传下去。定义写道:"Subsequent enablements of incoming branches are blocked until the Blocking Discriminator has reset."所有活动分支都到达后,它复位。见官方定义。

Dex 实现:拆分 Step 用 Join fork 每一轮,汇合 Step 等待 1 个分支(ForBranches)。下一轮的拆分 Step 先等待上一轮的 ForRemainingBranches,再 fork 下一轮。在此之前,下一轮的分支还不存在,所以下一轮的信号只会排队,不产生效果。

评级:+。复位在结构上挡住下一轮,不需要额外的 Step,也不需要轮次计数器。

示例:TS · Python · Go · Java · Rust

WCP-29 Cancelling Discriminator​

模式含义:最先到达的分支把控制传下去,并取消其他分支。见官方定义。

Dex 实现:拆分 Step 用 Join fork 各分支,汇合 Step 等待 1 个分支(ForBranches)。它的 decision 取消属于分支 Step type 的 sibling Step。Fork 在同一个 decision 里启动分支和汇合 Step,所以这些 sibling 正好是本轮的分支。

评级:+。同一个汇合 Step 既触发又取消。被取消的分支永远不会上报结果。

示例:TS · Python · Go · Java · Rust

WCP-30 Structured Partial Join​

模式含义:并行拆分成 m 个分支后,其中 n 个到达时控制就传下去,之后到达的不再传递。所有分支都到达后,汇合复位。见官方定义。

Dex 实现:每一轮,拆分 Step 用 Join fork m 个分支。汇合 Step 等待 n 个分支(ForBranches)。下一轮的拆分 Step 等待上一轮的 ForRemainingBranches,消费其余 m - n 个结果,然后 fork 下一轮。示例把被忽略的结果记在一个 Attribute 里。

评级:+。与 WCP-9 一样,Join 区分各轮,复位不需要额外的 Step,也不需要轮次计数器。

示例:TS · Python · Go · Java · Rust

WCP-31 Blocking Partial Join​

模式含义:m 个分支中有 n 个到达时,控制传下去。之后的启用会被阻塞,直到汇合复位。见官方定义。

Dex 实现:做法与 WCP-28 相同,只是等待 n 个分支(ForBranches)。ForRemainingBranches 复位汇合之后,下一轮的分支才会启动,所以在此之前下一轮的信号只会排队。

评级:+。与 WCP-28 一样,复位在结构上挡住下一轮。

示例:TS · Python · Go · Java · Rust

WCP-32 Cancelling Partial Join​

模式含义:m 个分支中有 n 个到达时,控制传下去,其余分支被取消。见官方定义。

Dex 实现:做法与 WCP-29 相同,只是等待 n 个分支(ForBranches)。汇合 Step 的 decision 取消它的 sibling 分支。

评级:+。与 WCP-29 一样,同一个汇合 Step 既触发又取消。

示例:TS · Python · Go · Java · Rust

WCP-33 Generalised AND-Join​

模式含义:每个输入分支都送来一个触发后,控制才传下去。某个分支上多余的触发会留给以后的触发。见官方定义。

Dex 实现:汇合 Step 用 AllOf 等待,每个输入分支一个 Channel。多余的消息会排队,汇合 Step 循环再次触发。

评级:+/-。汇合由 Channel 信号和 AllOf 等待组合而成,各分支必须发布信号。

示例:TS · Python · Go · Java · Rust

WCP-34 Static Partial Join for Multiple Instances​

模式含义:m 个实例运行。其中 n 个完成时,下一个任务开始。其余实例照常完成,全部完成后汇合复位。见官方定义。

Dex 实现:每一轮,拆分 Step 用 Join fork 同一 Step type 的 m 个实例。汇合 Step 等待 n 个实例(ForBranches)。下一轮的拆分 Step 等待上一轮的 ForRemainingBranches,然后 fork 下一轮。示例把被忽略的结果记在一个 Attribute 里。

评级:+。与 WCP-30 相同,只是分支换成了实例。

示例:TS · Python · Go · Java · Rust

WCP-35 Cancelling Partial Join for Multiple Instances​

模式含义:m 个实例运行。其中 n 个完成时,下一个任务开始,其余实例被取消。见官方定义。

Dex 实现:拆分 Step 用 Join fork m 个实例,汇合 Step 等待 n 个实例(ForBranches)。它的 decision 取消属于实例 Step type 的 sibling Step。

评级:+。与 WCP-32 相同,只是分支换成了实例。

示例:TS · Python · Go · Java · Rust

WCP-36 Dynamic Partial Join for Multiple Instances​

模式含义:其他实例运行时可以启动新实例,直到添加被禁止。每个实例完成后都会检查完成条件,条件成立时下一个任务开始。见官方定义。

Dex 实现:RPC 启动新实例,除非 Attribute 标志表明已禁止添加。汇合 Step 每次等待一个结果并检查条件。条件成立时,它设置这个标志,然后继续。

评级:+/-。汇合由 RPC、Attribute 标志、共享锁和每收到一个结果就重新等待的循环组合而成。

示例:TS · Python · Go · Java · Rust

WCP-37 Local Synchronizing Merge​

模式含义:各分支汇合,合并等待每个活动分支。它根据本地掌握的信息决定要等待多少个分支。见官方定义。

Dex 实现:与 WCP-7 一样,分叉的 Step 只用活跃的分支 fork 一个 Join。汇合 Step 等待 ForAllBranches。

评级:+。本地信息就是 round token 里的分支数,由 Fork 生成。

示例:TS · Python · Go · Java · Rust

WCP-38 General Synchronizing Merge​

模式含义:合并等待每个活动分支,或者等到 "it is not possible that any branch that has not yet been enabled will be enabled at any future time"。它适用于任何流程,包括带循环的非结构化流程。见官方定义。

Dex 实现:Attribute 记录仍能到达合并点的线程数。修改计数的每个 Step 都在这个 Attribute 上声明锁。把计数降到 0 的 Step 同时向 Channel 发布一条"完成"消息。合并 Step 等待这条消息。

评级:+/-。该模式要求合并点根据流程结构自行判断可达性。在 Dex 中,这一判断由应用代码在每次 GoTo 时做出。

示例:TS · Python · Go · Java · Rust

WCP-39 Critical Section​

模式含义:若干子流程被标记为临界区。在一个流程实例中,同一时间只有其中一个运行。见官方定义。

Dex 实现:一个 Channel 中只放一条令牌消息。每个区段的第一个 Step 等待令牌,最后一个 Step 把它发布回去。

评级:+/-。Attribute lock 只覆盖一个 Step 方法,所以由多个 Step 组成的区段用只含一条消息的 Channel 作为令牌。

设计模式:Critical Section。

示例:TS · Python · Go · Java · Rust

WCP-40 Interleaved Routing​

模式含义:一组任务中的每个任务以任意顺序运行一次,任意两个都不同时运行。全部完成后下一个任务开始。见官方定义。

Dex 实现:每个任务的 Execute 都在同一个 Attribute 上声明锁。汇合 Step 用 ForN 等待各任务的信号。

评级:+/-。路由由锁和 Channel 信号组合而成。与 WCP-17 一样,锁只覆盖一个 Execute。

示例:TS · Python · Go · Java · Rust

WCP-41 Thread Merge​

模式含义:同一分支中给定数量的线程合并成一个线程。见官方定义。

Dex 实现:Step 用指定数量的线程 fork 一个 Join,这些线程都属于同一个 Step type。每个线程以 EndBranch 结束。合并 Step 等待 ForAllBranches。

评级:+。每个线程就是 Join 的一个分支,由 Fork 计数。

示例:TS · Python · Go · Java · Rust

WCP-42 Thread Split​

模式含义:一个分支启动给定数量的线程。见官方定义。

Dex 实现:Step 返回 GoToMany,包含同一 Step type 的这么多个执行。

评级:+。GoToMany 启动这些线程。

示例:TS · Python · Go · Java · Rust

WCP-43 Explicit Termination​

模式含义:流程到达指定的结束节点时结束。剩余工作被取消,流程记为成功。见官方定义。

Dex 实现:Step 返回 ForceComplete。Dex 立即关闭 Flow,并取消其他所有活动 Step。

评级:+。ForceComplete 就是显式结束。

示例:TS · Python · Go · Java · Rust