New in 0.16.0

v0.16.1

Introduction

Workflow Examples

The code for those examples are available on Github.

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

You'll find all sources in the Infinitic's examples repository. We encourage you to explore the implementations and play with them.

Saga Workflow

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

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:

  • 1 point every 10 seconds
  • 200 points for completing a form
  • 500 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.
  • an addBonus method is used to tell the instance that the user did some actions
  • a burn method lets the user burn some points (if enough)

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 we restart the start method instead of looping within it.

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.

Previous
Interfaces As Contract