1Introduction

1.1What XJog is for

At its heart, XJog is a TypeScript library for running XState statecharts. In order to understand how it can help you, you need to know the basics of statecharts and XState.

It differs from the XState's built-in interpreter mainly in that it persists the state in a database. This way, logical processes that outlive the execution time of the runner, can be run. This principle is illustrated in figure 1. In-memory statecharts would disappear and their state would be lost, when the running process is terminated.

Fig. 1Basic principle of XJog

For example, a customer journey in an online shop could be modelled as a statechart and run by XJog. The charts could orchestrate the cart, price calculations, checkout and even delivery. The benefit is that the whole customer journey is in a single, well-defined state, with well-defined transitions between them.

Persisting server state is another example. A service in a Kubernetes cluster, could be terminated by Kubernetes itself, in case of running out of memory, for example. With state persisted with XJog, the service can continue right where it was interrupted.

Using SQLite database adapter, shipped with XJog, local applications too could persist state on disk without external database.

1.2Building blocks

There are three main components in XJog, as presented in figure 2. They are connected to a database using a persistence adapter.

Fig. 2Fundamental components of XJog

XJog is the main orchestrator for registering XState machines, managing ongoing activities, and managing timers. XJogMachine gives an interface for creating and accessing charts of their type. XJogChart is an interface to individual charts. It can be used to read state and send events.

In XState, all of these functions are taken care by an Interpreter.

1.3Instance lifecycle

XJog runs as a single instance per database. The purpose is to make sure that timing of deferred events, management of ongoing activities etc. are only handled in one place.

When starting up, a new instance will signal the previously running instance that it needs to shut down. During a grace period, it waits for the old XJog instance to release control of its charts. After the grace period has passed, it will take the rest without waiting.

Fig. 3XJog instance's lifecycle
Note
This design prevents usual horizontal scaling associated with stateless services, because XJog runs stateful activities and provides timing capabilities. External sharding can be applied if there is need for horizontal scaling.

1.4Delta stream

XJog has the capability of keeping a record of changes (deltas) in charts' state and events that caused them. This can be especially useful for monitoring, debugging and troubleshooting purposes, since the whole history can be travelled. Another application could be audit logging.

Fig. 4Delta records and time travel

It is possible to subscribe to real-time stream of changes.

1.5External identifiers

Often it's a requirement to assign charts an external identifier. XJog can register external key–value identifiers and access charts using them.

Example
A chart of machine checkout receives a case reference number from a payment broker. This number is registered as an external identifier paymentReference=14809. Later when the payment is cleared and the server receives a notification of this, the XJog chart is retrieved by this key–value pair, and it is sent an event payment cleared.
Fig. 5Use of external identifiers