Sequential Tasks

Subscribe here to follow Infinitic's development. Please ⭐️ us on Github!

For infinitic, a task is basically the method of a class. The implementation of this class is only needed in workers where the task is actually processed.

Within workflows, we should know only the interface of the class, used by the newTask workflow function to create a stub. Syntactically, this stub can be used as an implementation of the task:

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

    @Override
    public String greet(String name) {
        // synchronous call of HelloWorldService::sayHello
        String str = helloWorldService.sayHello(name);

        // synchronous call of HelloWorldService::addEnthusiasm
        String greeting =  helloWorldService.addEnthusiasm(str);

        // inline task to display the result
        inlineVoid(() -> System.out.println(greeting));

        return greeting;
    }
}
class HelloWorldImpl : Workflow(), HelloWorld {
    // create a stub for the HelloWorldService
    private val helloWorldService = newTask(HelloWorldService::class.java)

    override fun greet(name: String): String {
        // synchronous call of HelloWorldService::sayHello
        val str = helloWorldService.sayHello(name)

        // synchronous call of HelloWorldService::addEnthusiasm
        val greeting =  helloWorldService.addEnthusiasm(str)

        // inline task to display the result
        inline { println(greeting) }

        return  greeting
    }
}

Functionally, the stub behave as follows:

  • when the return value of the task is not known yet, this stub dispatches a message to Pulsar towards the workers asking for the task execution
  • when the return value is known in the workflow history, the stub returns this value.

For example, let's consider this line (from the HelloWorldImpl workflow above).

String str = helloWorldService.sayHello(name);
val str = helloWorldService.sayHello(name)

Here helloWorldService is a stub of the HelloWorldService interface. When a workflow executor processes the workflow and reaches this line for the first time, it will dispatch a HelloWorldService::sayHello task and stop its execution here.

After completion of this task, a workflow executor will process the workflow again, but with an updated workflow history. When reaching this line, the stub will - this time - provide the deserialized return value of the task, and the workflow will continue its execution.

And so on.

As we can guess now, the code below will guarantee that sayHello and addEnthusiasm tasks are processed sequentially, the second task using the return value of the first one.

String str = helloWorldService.sayHello(name);
String greeting =  helloWorldService.addEnthusiasm(str);
val str = helloWorldService.sayHello(name)
val greeting =  helloWorldService.addEnthusiasm(str)
Edit this page on GitHub Updated at Sat, Sep 10, 2022