Projections

§Projections

Note: The Projections API is marked with the @ApiMayChange annotation, meaning that we reserve the rights to change the API if necessary.

In Lagom, projections are processes consuming from a Persistent Entity Journal and handling each event via a read side table or emitting it into a broker topic via a TopicProducer. Here, a projection only refers to a ReadSideProcessor or a TopicProducer, not a broker subscriber.

Lagom takes care to handle as many instances of your projection as shards on your journal and then distribute those instances around the cluster so the load is balanced. By default, the multiple instances of your projection will be started but you can opt-out from that behavior using the setting:

lagom.projection.auto-start.enabled = true

§Projection status

Once up and running, you may query the state of your projections to ensure all the instances are up and running. You can also request a particular projection to stop or even a particular instance (aka worker) in a projection to stop.

Stopping and starting all the workers or a single worker of a projection is an asynchronous operation. Imagine we had a ReadSideProcessor called users-by-name that is reading the journal of a Users persistent entity and storing data into a SQL table. To stop that projection we would request the status of all workers to become Stopped. This request will propagate across the cluster and each node will make sure that any worker running locally that is part of the users-by-name projections is stopped. As workers switch from Started to Stopped they report back and we can observe their new status.

To request and modify the status of your projections inject a Projections instance provided by any of the Components that create projections (any persistence implementation or broker API implementation) in, for example, your ServiceImpl and use the provided methods.

The requested status is a volatile, in-memory value but it is replicated across your cluster. Only when the whole cluster is restarted you may have to request a particular status again. Also, because of its replicated nature, the requested status may be overwritten by multiple nodes on your cluster at the same time. The implementation is such that the last writer wins.

When a new instance of a projection worker is created the rules to decide its status are:

  • if worker’s requested status is known, use it; if not
  • use the default value in application.conf

Because the requested status is a distributed, in-memory value, there is an edge case you will have to consider when you need a worker to be stopped. When starting a new node and having that node join an existing cluster, it is possible that some workers are spawned in the node before the requested status value is received from the peer nodes. In that case, the default lagom.projection.auto-start.enabled will be used to decide if the spawned worker should be stopped or started. If your default is enabled = true but the in-memory, replicated value is Stopped then there’s a race condition and you could observe your worker start-and-then-stop. To prevent the start-and-then-stop behavior, opt-out of lagom.projection.auto-start.enabled = true and always handle worker startup using the methods startAllWorkers/startWorker on the Projections API.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.