Redis Batched

A Redis batch projection is a atomic projection based on Redisson RBatch. Like Redis transactional projections, also this projection type is more lightweight than Spring transactional projections. No Spring PlatformTransactionManager is needed, the RBatch object of the Redisson library is enough.

Working with a Redis batch projection is asynchronous as multiple commands are collected and executed later in an atomic way (all or none).

Motivation

You would want to use Redis Batched for two reasons:

  • atomicity of factStreamPosition updates and your projection state updates
  • increased fact processing throughput

The performance bit is achieved by skipping unnecessary factStreamPosition updates and (more importantly) by reducing the number of operations on your Redis backend by using a redisson batch instead of single writes for bulkSize updates. The bulkSize is configurable per projection via the @RedisBatched annotation.

Redisson batches improve performance significantly by collecting operations and executing them together as well as delegating all possible work to an async thread. It has the effect, that you cannot read non-executed (batched) changes. If this is unacceptable for your projection, consider Redis transactional projections. See the Redisson documentation for details.

Other than a transaction, writes registered (but not yet executed) on a Redis batch can not be read.

A Redis batch projection, therefore, is recommended for projections which

  • handle a lot of events and
  • don’t require reading the current projection state in an event handler.

For an alternative that allows access to the projection state during event handling, see Redis transactional projection.

Configuration

In order to make use of redisson RBatch support, the necessary dependency has to be included in your project:

    <dependency>
        <groupId>org.factcast</groupId>
        <artifactId>factcast-factus-redis</artifactId>
    </dependency>

Structure

A Redis batch projection supports managed- or subscribed projections and is defined as follows:

  • it is annotated with @RedisBatched
  • it implements RedisProjection revealing the RedisClient used
  • it provides the serial number of the projection via the @ProjectionMetaData annotation
  • the handler methods receive an additional RBatch parameter

This structure is similar to a Redis transactional projection, only the @RedisBatched annotation and the RBatch method parameter differ.

Example

@Handler
void apply(SomethingHappened fact, RBatch batch) {
    myMap = batch.getMap( ... ).putAsync( fact.getKey() , fact.getValue() );
}

a full example can be found here