使用 Jolie 存储工作流状态

Storing workflow state with Jolie

我想了解 Jolie 如何实现工作流程的弹性。

您可以将 Jolie 语言的三个组件混合到 save/load 工作流状态和程序故障恢复代码中:

  • 朱莉变量,是树;
  • 一些标准库支持 Jolie 树的编组和解组以及 file/database 交互;
  • 用于处理异常行为的语言fault handling mechanisms

Jolie 微服务实例的状态是一棵树(类似于 XML 和 JSON 结构)。实际上,虽然在 Jolie a = 5 中回忆起在其他语言中发现的熟悉的变量赋值,但实际发生的是,在实例执行赋值的状态下,我们创建了一个节点 a 并赋值给 a5。反之亦然,当我们在 Jolie 程序中编写 a 时,我们正在访问存储在节点 a 下的值。同理,a.b = 6表示在a下创建子节点b,并赋值6.

在发送和接收结构化数据时,使用语言中的原生树数据结构非常有用,因为 Jolie 通过其自动将其树形变量转换为用于与某些外部 client/server 通信的格式端口。然而,树形变量也相当容易marshal/unmarshal。例如,我们可以通过调用 JSON (or XML) library and either use the File or Database 持久化库来转换 Jolie 树变量的当前状态。

我在下面组装了一个简单的例子来说明我的观点。在示例中,我使用过程 saveStateloadState 来保存和加载存储在变量 process_state 下的值,该变量是包含工作流中使用的所有相关值的根变量。工作流从 main 块开始,我们在其中保存一些数据并打印出来以供参考(操作 valueToPrettyStringprintln)。然后,我们保存当前状态 (saveState) 并继续 stage1。由于变量 process_state.c 等于 "bad" 我们抛出一个错误 (MyFault)。 install 块捕获错误并执行过程 recv_stage1。该过程丢弃程序先前的错误状态,恢复保存在文件中的状态和 "repairs" 变量 process_state.c。完成后,我们再次执行 stage1

include "console.iol"
include "json_utils.iol"
include "string_utils.iol"
include "file.iol"

define saveState
{
  getJsonString@JsonUtils( process_state )( marshalled_state.content );
  writeFile@File( marshalled_state )();
  undef( marshalled_state.content )
}

define loadState {
  undef( process_state );
  readFile@File( marshalled_state )( marshalled_state.content );
  getJsonValue@JsonUtils( marshalled_state.content )( process_state );
  undef( marshalled_state.content )
}

define recv_stage1 {
  scope( recv_stage1 ){
     loadState;
     process_state.c = "fine";
     valueToPrettyString@StringUtils( process_state )( state_pretty_print );
     println@Console( state_pretty_print )()
  }
}

define stage1 {
  scope( stage1 ){
    install( MyFault => 
      println@Console( "MyFault, loading saved state" )(); recv_stage1; stage1 );
    if ( process_state.c == "bad" ){
      throw( MyFault )
    } else {
      println@Console( "Everything went " + process_state.c )()
    }
  }
}

main
{
  marshalled_state.filename = "instance_XXX.json";
  with ( process_state ){
    .a = 42;
    .b << "I" { .love = "very", .much = "jolie" };
    valueToPrettyString@StringUtils( process_state )( state_pretty_print );
    println@Console( state_pretty_print )();
    saveState;
    .c = "bad";
    stage1
  }
}

这种分级也可用于从崩溃中恢复(例如,通过指示一个变量是到达的最后一个阶段)。

Jolie 还提供了一些高级结构来处理 termination and compensation 工作流,有助于避免保存损坏的阶段并强制执行交易行为。

参考资料

  • Fabrizio Montesi、Claudio Guidi 和 Gianluigi Zavattaro。 (2014)。与 Jolie 一起进行面向服务的编程。在 A. Bouguettaaya、Q. Z. Sheng 和 F. Daniel(编辑),Web 服务基础(第 81-107 页)中。施普林格 https://doi.org/10.1007/978-1-4614-7518-7_4
  • Fabrizio Montesi、Claudio Guidi、Ivan Lanese 和 Gianluigi Zavattaro。 (2008)。面向服务的应用程序的动态故障处理机制。 https://doi.org/10.1109/ECOWS.2008.20