i2Zeebe

From i2Rest
Revision as of 19:11, 30 August 2023 by Alexei.baranov (talk | contribs) (Show Zeebe status)
Jump to: navigation, search


This page is under construction!


i2Zeebe works as a bridge between IBM i server and Zeebe process automation engine. You can use i2Zeebe as a native equivalent of zbctl utility or as Zeebe client library for use in your ILE RPG/C code. i2Zeebe represents IBM i program written on ILE C, which can be called from command line or from any IBM i program. With i2Zeebe, you can interact with almost any Zeebe API (gRPC) directly from IBM i server.

What is Zeebe

According to the vendor, Zeebe is the workflow and decision engine that powers Camunda. Zeebe's cloud-native design provides the performance, resilience, and security enterprises need to future-proof their process orchestration efforts.

Quote:
With Zeebe you can:

  • Define processes graphically in BPMN 2.0.
  • Choose any gRPC-supported programming language to implement your workers.
  • Build processes that react to events from Apache Kafka and other messaging platforms.
  • Use as part of a software as a service (SaaS) offering with Camunda Platform 8 or deploy with Docker and Kubernetes (in the cloud or on-premises) with Camunda Platform 8 Self-Managed.
  • Scale horizontally to handle very high throughput.
  • Rely on fault tolerance and high availability for your processes.
  • Export processes data for monitoring and analysis (currently only available through the Elasticsearch exporter added in Camunda Platform 8 Self-Managed).
  • Engage with an active community.

For documentation on deploying Zeebe as part of Camunda Platform 8 Self-Managed, refer to the deployment guide.

What is i2Zeebe

i2Zeebe is native IBM i program which combines abilities of Zeebe CLI client and Zeebe client library for use on IBM i server platform. It uses parameters passed from command line or from calling program, to perform interaction to Zeebe process engine.

Examples of i2Zeebe usage

Command line interface

Topology request

call i2zeebe parm('Topology' '--gateway' 'http://gateway:26500' '--sync' '--printResponse=joblog')

Depending on your Zeebe cluster configuration, this call will produce information in the job log like this (formatted here for clarity):

{
  "http2_status": 200,
  "http2_error": 0,
  "grpc_status": 0,
  "TopologyResponse": {
    "brokers": [
      {
        "nodeId": 0,
        "host": "node0",
        "port": 26501,
        "partitions": [
          {
            "partitionId": 1,
            "role": "follower",
            "health": "healthy"
          },
          {
            "partitionId": 2,
            "role": "follower",
            "health": "healthy"
          },
          {
            "partitionId": 3,
            "role": "follower",
            "health": "healthy"
          }
        ],
        "version": "8.2.7"
      },
      {
        "nodeId": 1,
        "host": "node1",
        "port": 26501,
        "partitions": [
          {
            "partitionId": 1,
            "role": "follower",
            "health": "healthy"
          },
          {
            "partitionId": 2,
            "role": "leader",
            "health": "healthy"
          },
          {
            "partitionId": 3,
            "role": "follower",
            "health": "healthy"
          }
        ],
        "version": "8.2.7"
      },
      {
        "nodeId": 2,
        "host": "node2",
        "port": 26501,
        "partitions": [
          {
            "partitionId": 1,
            "role": "leader",
            "health": "healthy"
          },
          {
            "partitionId": 2,
            "role": "follower",
            "health": "healthy"
          },
          {
            "partitionId": 3,
            "role": "leader",
            "health": "healthy"
          }
        ],
        "version": "8.2.7"
      }
    ],
    "clusterSize": 3,
    "partitionsCount": 3,
    "replicationFactor": 3,
    "gatewayVersion": "8.2.7"
  }
}

Activate jobs

Lets assume that we have published simple business process with service task that has type I2ZEEBE to our Zeebe cluster (http://gateway:26500):
I2zeebe simple.png
Now we can start the process, for example from Camunda Modeller (press Start process button in the bottom of Modeller interface:
I2zeebe simple start.png

At this step, Zeebe process engine should wait for activation of I2ZEEBE task by some worker. Let's do it from IBMi command line interface:
call i2zeebe parm('ActivateJobs' '--sync' '--printResponse' '--gateway' 'http://gateway:26500' '--jobType' 'I2ZEEBE' '--worker' 'I2ZEEBE')

Resulting job log:

{
  "http2_status": 200,
  "http2_error": 0,
  "grpc_status": 0,
  "ActivateJobsResponse": {
    "jobs": [
      {
        "key": 6755399441390948,
        "type": "I2ZEEBE",
        "processInstanceKey": 6755399441390943,
        "bpmnProcessId": "i2Zeebe_simple",
        "processDefinitionVersion": 1,
        "processDefinitionKey": 2251799814019882,
        "elementId": "i2Zeebe_task",
        "elementInstanceKey": 6755399441390947,
        "customHeaders": "{}",
        "worker": "I2ZEEBE",
        "retries": 3,
        "deadline": 1693331966076,
        "variables": "{}"
      }
    ]
  }
}


Job has been activated for our job worker I2ZEEBE for 30 seconds (default value of --timeout).

CompleteJob

Now we will complete job activated on the previous step.
call i2zeebe parm('CompleteJob' '--gateway' 'http://gateway:26500' '--sync' '--printResponse' 'joblog' '--jobKey' '6755399441390948')

Joblog shows the response:

{
  "http2_status": 200,
  "http2_error": 0,
  "grpc_status": 0,
  "CompleteJobResponse": {}
}                                                               

Call from ILE C program

When using as Zeebe client library, i2Zeebe supports two modes of parameters passing - RPG mode and shell mode. We will demonstrate shell mode here:

#include <stdio.h>
#include "i2zeebe.h"

int main(int argc, char *argv[]) {

   gateway_protocol_TopologyResponse TopologyResponse;
   int grpc_status;
   int nghttp2_error;
   int http2_status;
   char grpc_message[1000];
   int grpc_message_len=sizeof(grpc_message);

   // Get Zeebe cluster status information
   I2ZEEBE("Topology", 
           "--sync",
           "--gateway", "http://gateway:26500",
           "--printResponse", "stdout",
           "--response", &TopologyResponse,
           "--grpcStatus", &grpc_status,
           "--nghttp2Error", &nghttp2_error,
           "--http2Status", &http2_status,
           "--grpcMessage", grpc_message,
           "--grpcMessageLen", grpc_message_len);

   printf("Zeebe gateway version: %s\n", TopologyResponse.gatewayVersion);

   // Cleanup memory allocated by previous call
   I2ZEEBE("Cleanup", "Topology", &TopologyResponse);

   return 0;
}

Call from ILE RPG program

To call i2Zeebe from RPGLE program, it is recommended to use pass parameters in RPG mode. In this mode, i2Zeege accepts fixed number of parameters - 5 for applying some action or 2 for releasing data allocated by the action:

/Copy i2ZeebeCpy                                              
/Free                                                         
   
   // i2ZeebeCommon, i2TopologyResponse are defined in i2ZeebeCpy
                                                           
   i2ZeebeCommon.gateway = 'http://gateway:26500'+x'00';
   i2ZeebeCommon.printResponse = 1;
   i2ZeebeCommon.syncCall = 1;

   // Call Topology request
   I2ZEEBE('I2Z0100':                          // Request identifier. I2Z0100 = TopologyRequest
           i2ZeebeCommon:                      // Common parameters for i2Zeebe calls
           *NULL:                              // TopologyRequest parameters (none)
           %Addr(i2ZTopologyResponse):         // This structure will be filled with results
           *NULL);                             // Exit program

   // 
   // ... do some stuff with returned data
   //

   // Clean up returned data
   I2ZEEBEX('I2Z0100':                 
           %Addr(i2ZTopologyResponse));
                                       
    Return;                            
/End-Free

Zeebe Job Worker

i2Zeebe supports synchronous and asynchronous communications with Zeebe gateway. It allows to build native IBMi Zeebe job workers, as shown below (assuming happy path only):

#include <stdio.h>
#include <mih/rslvsp.h>

#include "i2zeebe.h"

// Pointer to this *PGM object. 
// We will use this program as main worker loop and 
// as callback function for ActivateJobs command
static void *i2zeebe_t1 = NULL;

int main(int argc, char *argv[]) {

   int first_call = 0;

   // First call - I2ZEEBE_T1 has been called as a Worker
   if(!i2zeebe_t1) {
      first_call = 1;
      
      // Save pointer to itself
      i2zeebe_t1 = rslvsp(_Program, "I2ZEEBE_T1", "*LIBL", _AUTH_NONE);
   }


   if(!first_call) {

      // Good news, we get a Job!
      // I2ZEEBE_T1 has been called from i2Zeebe event loop
      // and works as a ActivateJobs callback function
      //
      // In this mode, program will receive response from Zeebe cluster
      // with return codes/messages from transport layer

      gateway_protocol_ActivateJobsResponse *response = (void *)argv[2];
      char activatedJob[20];
      int i;
      
      // Job processing is simple - just
      // submit CompleteJob messages with some
      // dummy payload

      for(i=0;i<response->jobs_count;i++) {

         sprintf(activatedJob, "%lld", response->jobs[i].key);

         Qp0zLprintf("Completing %s\n", activatedJob);

         I2ZEEBE("CompleteJob",
                 "--gateway", "http://gateway:26500",
                 "--printResponse", "joblog",
                 "--jobKey", activatedJob,
                 "--variables", "{\"someData\":123}");
      }
   }

   // Subscribe to jobs with this program as a callback 
   I2ZEEBE("ActivateJobs", 
           "--gateway", "http://gateway:26500",
           "--jobType", "I2ZEEBE",
           "--responseExit", &i2zeebe_t1);


   // First call - start i2Zeebe event loop 
   if(first_call) {
      I2ZEEBE("Resume");
   }

   return 0;
}

Quickstart

Installation

  1. Download file i2Zeebe_Install.ZIP
  2. Put it to your home directory or to any other folder on IFS
  3. Open emulator session and run following commands:
    1. CHGCURDIR <directory_where_ZIP_copied>
      you'll see message "Current directory changed."
    2. QSH CMD('jar xMvf i2Zeebe_Install.ZIP')
      It will extract SAVF from zipped file, you'll see message "inflated: I2ZEEBE.SAVF"
    3. CRTSAVF FILE(QTEMP/I2ZEEBE)
      File I2ZEEBE created in library QTEMP.
    4. CPYFRMSTMF FROMSTMF(i2zeebe.savf) TOMBR('/qsys.lib/qtemp.lib/i2zeebe.file') MBROPT(*REPLACE)
      "Stream file copied to object."
    5. RSTLICPGM LICPGM(0AI2R10) DEV(*SAVF) SAVF(QTEMP/I2ZEEBE)
      *PGM objects for product 0AI2R10 option *BASE release *FIRST restored.
  4. Verify i2Zeebe installed:
    1. WRKLICINF PRDID(0AI2R10)
      i2Rest IBMi Zeebe client should be displayed
    2. WRKOBJPDM I2ZEEBE
      You'll see objects in I2ZEEBE product library

Start Zeebe instance

If you don't have Zeebe instance available yet, the easiest way to start playing with standalone Zeebe is to install it using Docker compose, as described in official documentation

All we need to continue is access to Zeebe interface from our IBMi server. We need network access to the Zeege gateway server and the port on which the Zeebe listens for gRPC requests (typically it is port 26500).

Show Zeebe status

Assuming that Zeebe server is accessible as 'gateway', we can try to call Zeebe to get its status, as described above:

call i2zeebe parm('Topology' '--gateway' 'http://gateway:26500' '--sync' '--printResponse=joblog')

i2Zeebe parameters

TODO

Shell mode

In Shell mode, calling format is following:

Command line/QCMD:

call i2Zeebe parm(<Command> [command-specific options] [common options])

When calling from command line, all parameters should be enclosed to single quotas

From QShell:

i2Zeebe <Command> [command-specific options] [common options]

Common options

Option Description
--gateway <address> Required for all commands, with except for Cleanup, Pause and Resume. Specifies address of Zeebe gateway, for example
--gateway http://gateway:26500

Command specific options

Command Options Description

RPGLE mode

TODO

i2Zeebe binaries

TODO

Header files

TODO