New version 0.13.0!

v0.13.3

Introduction

Workflow Examples

Infinitic's power and flexibility can be best understood through examples. Here, we provide several workflow examples to showcase its capabilities.

Bookings and Saga

Consider a booking process that includes a car rental, a flight, and a hotel reservation. All these bookings must either succeed or fail together. If any booking fails, the others that succeeded should be canceled.

Bookings and Saga

The Services

Each service involved in this process, like HotelBookingService, has methods to book and cancel a booking.

The BookingWorkflow orchestrates the complete booking process:

The BookingWorkflowImpl class in Java or Kotlin performs the bookings in parallel and cancels them if any one of them fails. The code structure is as follows:

  • Services for car rental, flight, and hotel are initialized.
  • Bookings are dispatched in parallel.
  • Results are awaited and checked.
  • If any booking fails, successful ones are canceled.

The workflow is a perfect example of the Saga pattern in distributed transactions.

In a workflow, when you use the dispatch function, it starts a task without interrupting the workflow's ongoing process. If you use dispatch multiple times, it will run several tasks at the same time, in parallel. The dispatch function gives back a Deferred object. When you use the await() method on this Deferred object, it makes the workflow pause and wait until the task is finished, and then it provides the task's result.

Monthly invoicing

Imagine a workflow where, every month, we need to:

  • Gather user metrics
  • Charge the user's payment card
  • Generate and send an invoice

Monthly invoicing

With Infinitic, this process does not require a cron job. The InvoicingWorkflowImpl handles this monthly routine:

  • It uses services like ConsumptionService and PaymentService.
  • The workflow waits until the first day of the next month.
  • It calculates the payment amount and processes the payment.
  • An invoice is generated and sent to the user.

In a workflow, when you use a timer and await it, the workflow pauses until a specific time (Instant) or for a set period (Duration). During this wait, no resources are being used.

In a workflow, every step must be deterministic, which is why commands like LocalDate.now() should be part of a task. The inline function is used to create what's called a pseudo-task, which is integrated directly into the workflow.

A workflow should not have too many tasks, so it's best to avoid loops. In this example, the number of iterations is limited (running for 10 years results in just 120 iterations) and there are only 7 tasks in each iteration. Therefore, this setup is manageable and appropriate.

Loyalty program

Consider a loyalty program where users earn points for various actions:

  • 10 points weekly
  • 100 points for completing a form
  • 100 points for completing an order
  • Users can also burn points

Loyalty program

LoyaltyWorkflowImpl is all we need to manages this program:

  • Points are stored and updated within the workflow.
  • Different methods update points for different actions.
  • The workflow runs as long as the user is active.

An Infinitic client, or another workflow, can invoke methods of an active workflow. While it's possible for multiple methods of the same workflow instance to operate concurrently, only one method runs at any specific moment. You can think of this as an asynchronous, yet single-threaded execution.

Properties within workflows serve as a way to store information that can be modified by various methods.

A workflow shouldn't have too many tasks, which is why it's advisable to steer clear of loops. In this scenario, the number of iterations is controlled (for example, operating over 10 years results in just 560 iterations) with only 2 tasks in each iteration. This amount is acceptable and manageable.

Location Booking

Imagine an Airbnb-like service where travelers request bookings from hosts.

  • Travelers' requests are sent to hosts.
  • If the host responds positively, the traveler pays a deposit.
  • Both parties are then notified of the booking.

Location Booking

LocationBookingWorkflowImpl handles this process:

This workflow showcases complex decision-making and communication between multiple parties.

We have the ability to dispatch external signals to a workflow to inform it of an event or change. A signal is a type of serializable object. For a workflow to receive and process a signal, it needs to be equipped with a channel.

This example with the `PaymentWorkflow`` demonstrates that a workflow can launch another sub-workflow, either in a synchronous or asynchronous manner. This capability unlocks endless possibilities.

Repositories examples

  • Hello World: a simple workflow with 2 sequential task. (java, kotlin)
  • Booking Workflow: a saga pattern implementation with three tasks. (java, kotlin)
  • Loyalty Workflow: A loyalty program with points updated through methods. (java, kotlin)
  • Sync Workflow: this workflow continuously receives events, with each event initiating a sequence of three tasks. These tasks must be completed before the workflow can proceed to handle the next event (java)
Previous
Event-Driven