Workflow Syntax

Infinitic is still in active development. Subscribe here to follow its progress.

Here is an example of workflow implementation, from our Hello World app:

import hello.world.tasks.HelloWorldService;
import io.infinitic.workflows.Workflow;

public class HelloWorldImpl extends Workflow implements HelloWorld {
    // create a stub from HelloWorldService interface
    private final HelloWorldService helloWorldService = newTask(HelloWorldService.class);

    @Override
    public String greet(String name) {
        // dispatch HelloWorldService::sayHello task and wait for its completion
        String str = helloWorldService.sayHello(name);

        // dispatch HelloWorldService::addEnthusiasm task and wait for its completion
        String greeting = helloWorldService.addEnthusiasm(str);

        // run an inline task (returning void)
        inlineVoid(() -> System.out.println(greeting));

        // workflow return value
        return greeting;
    }
}
import hello.world.tasks.HelloWorldService
import io.infinitic.workflows.Workflow

class HelloWorldImpl : Workflow(), HelloWorld {
    // create a stub from HelloWorldService interface
    private val helloWorldService = newTask(HelloWorldService::class.java)

    override fun greet(name: String?): String {
        // dispatch HelloWorldService::sayHello task and wait for its completion
        val str = helloWorldService.sayHello(name)

        // dispatch HelloWorldService::addEnthusiasm task and wait for its completion
        val greeting = helloWorldService.addEnthusiasm(str)

        // run an inline task
        inline { println(greeting) }

        // workflow return value
        return  greeting
    }
}

As we can see above, a workflow is directly coded in plain java/kotlin - but the processing of this workflow is actually event-based, making Infinitic really scalable and error-resilient.

For more detailed explainations, please read under the hood of a event-driven workflow engine.

At each step, the state of the workflow is automaticaly saved, including the status (runnning, completed...) and output of previous steps. When something new is happening - for example a task completion - the workflow is processed again from the start, but the history is used to skip every step already completed.

The workflow implementation must contain only the deterministic description of the flow of tasks.

A workflow class must

  • extend io.infinitic.workflows.Workflow
  • be public and have an empty constructor
  • have serializable parameters and return value for its methods

A workflow class must be deterministic and without side effects. As a consequence, the following actions must not be used in workflows (but are perfectly fine in tasks):

  • multi-threading
  • performing database requests
  • performing any file operation
  • performing API calls
  • using environment variables*
  • using current date*
  • using random values*

*can be used in workflow as inline tasks.

the history of a workflow should not grow indefinitely, so we should avoid having more than a few thousands tasks in a workflow. If you need more, consider using child workflows to distribute your work.

For example, to manage 1 million tasks, we may have a workflow dispatching 1000 child-workflows managing 1000 tasks each)

Edit this page on GitHub Updated at Mon, Oct 25, 2021