Redis Transactional
A Redis transactional projection is a transactional projection based on Redisson RTransaction.
Compared to a Spring transactional projection, a Redis transactional projection is more lightweight since
- transactionality is directly provided by
RTransaction
. There is no need to deal with Spring’sPlatformTransactionManager
- the fact stream position is automatically managed (see example below)
Motivation
You would want to use Redis Transactional 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 bulkSize
updates with one redisson transsaction
instead of single writes.
The bulkSize
is configurable per projection via the @RedisTransactional
annotation.
Working with a Redis transactional projection you can read your own uncommitted write. For this reason, a Redis transactional projection is best used for projections which need to access the projection’s data during the handling of an event.
Configuration
In order to make use of redisson RTransaction 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 transactional projection can be a managed- or a subscribed projection and is defined as follows:
- it is annotated with
@RedisTransactional
(optional when using the default values and extending one of Factus’ abstract classes mentioned below) - it implements
RedisProjection
revealing theRedisClient
used - it provides the revision number of the projection via the
@ProjectionMetaData
annotation - the handler methods receive an additional
RTransaction
parameter
Note
Factus provides convenient abstract classes for managed and subscribed projections:
AbstractRedisTxManagedProjection
AbstractRedisTxSubscribedProjection
Example
@Handler
void apply(SomethingHappened fact, RTransaction tx) {
myMap = tx.getMap( ... ).put( fact.getKey() , fact.getValue() );
}
a full example can be found here