Skip to content

Persistence

Stetson Robinson edited this page Apr 10, 2020 · 9 revisions

IMPORTANT: This Kogito wiki is deprecated. For the latest Kogito documentation, see the Kogito documentation page. To contribute to Kogito documentation, see the master-kogito branch of the kie-docs repository in GitHub.

Overview

Kogito supports (since version 0.3.0) a runtime persistence for workflows. That allows users to configure key value based storage backed by Infinispan to persist data (including active nodes and process instance variables) to preserve it across restarts.

Version of Infinispan currently used is 10.0.0.CR1

Configure

To enable it in the project there are two steps required

  • add maven dependencies

  • configure connection with Infinispan server

Note
as prerequisite Infinispan server must be installed and available over network

Configuration will differ depending on selected runtime (Quarkus or SpringBoot)

Quarkus

Add maven dependencies

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-infinispan-client</artifactId>
</dependency>
<dependency>
  <groupId>org.kie.kogito</groupId>
  <artifactId>infinispan-persistence-addon</artifactId>
  <version>${kogito.version}</version>
</dependency>

Configure connection with Infinispan server

Add following into the src/main/resources/application.properties file

quarkus.infinispan-client.server-list=localhost:11222
Note
Adjust the host and port number according to your Infinispan server installation.

SpringBoot

Add maven dependencies

<dependency>
  <groupId>org.kie.kogito</groupId>
  <artifactId>infinispan-persistence-addon</artifactId>
  <version>${kogito.version}</version>
</dependency>
<dependency>
  <groupId>org.infinispan</groupId>
  <artifactId>infinispan-spring-boot-starter-remote</artifactId>
  <version>${infinispan-spring-boot.version}</version>
</dependency>

Configure connection with Infinispan server

Add following into the src/main/resources/application.properties file

infinispan.remote.server-list=127.0.0.1:11222
Note
Adjust the host and port number according to your Infinispan server installation.

This is minimal configuration to make it work and obviously does not cover all possible aspects of configuration. Refer to Infinispan configuration options based on selected runtime to learn more.

What is persisted?

Runtime persistence focuses mainly on storing data that are required to resume workflow execution for particular process instance. Regardless if the process is public or provide as long as it’s not completed it subject for persistence.

Node instances

Node instances that are currently active, so called wait states, are persisted when process instance finished execution but have not reached end state (completed or aborted). This means that only information required to resume are persisted. There might be one or more active nodes instances stored at any given point in time.

Process instance variables

All data that are included in the process instance are stored together with the process instance itself. These must be marshalled into a bytes format so it can be easily transferred over the wire and persisted into the key value storage. The marshalling and unmarshalling is implemented based on ProtoBuf and requires to have schema and marshallers available to know how to deal with given type of data.

Luckily Kogito comes with out of the box support to generate both marshallers and Protobuf schema (aka proto files). During build of the project, Kogito will scan all process definitions and extract information about data that are used within these business assets.

Next, based on the unique data types (regardless how many processes reference given type) a proto file (kogito-application.proto) is generated that builds up a complete schema for the application. This file is stored in the target/classes/persistence/ folder after successful build.

syntax = "proto2";
package org.kie.kogito.examples;
import "kogito-types.proto";

message Order {
        option java_package = "org.kie.kogito.examples.demo";
        optional string orderNumber = 1;
        optional bool shipped = 2;
        optional double total = 3;
}
message Person {
        option java_package = "org.kie.kogito.examples.demo";
        optional bool adult = 1;
        optional int32 age = 2;
        optional string name = 3;
}
Note
Each kogito-application.proto file imports kogito-types.proto which defines base types automatically managed by Kogito.

Based on the kogito-application.proto file, marshallers are also generated and configured in the application so whenever particular data type is used in process instance it can be successfully marshalled and unmarshalled.

Marshallers are based on the subproject of Infinispan called protostream.

Supported data types

Main rule is to try to stick to POJO/JavaBeans as data types that represent process variables. While doing that out of the box generation will provide most benefits. Diverging from it pose quite high probability of failed generation and by that failed build.

Currently following data types are supported:

Type Description Since version

java.lang.String

Basic text type

0.3.0

java.lang.Integer

Basic number type

0.3.0

java.lang.Long

Extended size number type

0.3.0

java.lang.Float

Basic floating point number type

0.3.0

java.lang.Double

Extended size floating point number type

0.3.0

java.util.Date

Basic date type

0.3.0

POJO/JavaBean

POJO type that is build up from above simple types

0.3.0

POJO/JavaBean with another POJO

POJO type that is build up from above simple types and another POJOs

0.3.0

POJO/JavaBean with list of POJOs

POJO type that is build up from above simple types and another POJOs and List of POJOs

0.3.0

How it is persisted?

Process instance is persisted as soon as it reaches a wait state, meaning it does not execute anymore but has not reached yet the final state (complete or abort). An example of such wait state is user task, or signal catch event. At this stage the complete snapshot of process instance is taken, that includes

  • process instance metadata such as id, proces id, state, description, start date etc.

  • active node instances including their variables

  • process instance variables

Process instance metadata is persisted with predefined protobuf schema that is aware of the metadata and support node instance that can be wait states.

Process instance and node instance variables are persisted based on the generated protobuf schema and generated marshallers. This allows to use custom data types within the process definition and ensure the data is properly persisted during execution.

In case of straight-through process instances, persistence is not even invoked as there is nothing to be stored since process instance has reached its final state.

Each process definition will have its own cache for storing runtime information. That is based on process id and as such will be named in the Infinispan server. Cache is automatically created if it does not exists. That kind of setup allows for easier maintenance of individual process instance data and reduces concurrency on the cache instances as well.

How is it controlled?

Persistence is plugged into Unit of Work that allows to level of control of the execution. The default implementation delays any persistence related work until the unit of work is completed. That usually means a request is about to finish or the message is consumed.