Introduce dedicated methods utilizing the ReactiveMessageListenerContainer to create a stream of Messages via ReactiveRedisTemplate.
redisTemplate.listenToChannel("channel1", "channel2").doOnNext(msg -> {
// message processing ...
}).subscribe();
Add close-/destroyLater methods avoiding blocking shutdown of connections and containers.
Original Pull Request: #295
We now provide sending and receiving of Redis Pub/Sub messages with reactive connections. Messages can be sent with ReactiveRedisTemplate and received as infinite stream through ReactiveRedisMessageListenerContainer. ReactiveRedisMessageListenerContainer uses a single connection to multiplex different subscriptions.
Reactive Pub/Sub supports Standalone, Sentinel and Redis Cluster setups.
ReactiveRedisConnectionFactory factory = …;
ReactiveRedisTemplate<String, String> template = new ReactiveRedisTemplate<>(factory, RedisSerializationContext.string());
Mono<Long> publish = template.convertAndSend("hello!", "world");
ReactiveRedisMessageListenerContainer container = new ReactiveRedisMessageListenerContainer(factory);
Flux<ChannelMessage<String, String>> channelMessages = container.receive(new ChannelTopic("foo"));
Flux<PatternMessage<String, String, String>> patternMessages = container.receive(new PatternTopic("foo"));
//
container.destroy();
Original Pull Request: #295
We now provide factory methods to create default serializers/deserializers accepting ClassLoader.
RedisSerializer.java(ClassLoader)
RedisSerializationContext.java(ClassLoader)
RedisCacheConfiguration.defaultCacheConfig(ClassLoader)
Original Pull Request: #333
We now read and convert constructor property values through MappingRedisConverter.readProperty(…) to apply proper conversion. This way, constructor properties are read through the same methods as instance properties allowing to read back nested level entities.
Previously, we were only reading simple properties or properties associated with a registered Converter.
Original Pull Request: #329
Remove DefaultRedisMapEntry as it's no longer required. Simplify test to unit test to reduce test scope and test run time.
Original pull request: #326.
Redis has a limitation of 1024 * 1024 parameters]() for bulk operations.
To receive more than 1024 * 1024 - 1 entries with entrySet(), we can directly use the HGETALL command instead of first fetching the keys with HKEYS and then fetching the values with HMGET.
See also: https://github.com/antirez/redis/blob/4.0.9/src/networking.c#L1200
Original pull request: #326.
We now no longer set ifValueNotExists() in ReactiveHashCommands.hMSet to always upsert hash entries. Previously, we called HSETNX if hMSet was called with a single tuple which did not overwrite existing entries.
Align return value of hMSet to return always true as calling internally HSET returns 1 only on newly set hash fields and setting an existing field resulted previously in false.
Original Pull Request: #325
Introduce marker interface RedisConfiguration along with several others providing access to specific setup scenarios like cluster and sentinel.
Original Pull Request: #306
We now provide RedisElastiCacheConfiguration to configure connections to AWS ElastiCache for Redis services with optional read replicas.
RedisElastiCacheConfiguration elastiCache = new RedisElastiCacheConfiguration("redis-node-1.elasticache.aws.com")
.node("redis-node-2.elasticache.aws.com");
LettuceConnectionFactory factory = new LettuceConnectionFactory(elastiCache, configuration);
Original Pull Request: #306
We now share Lettuce Cluster connections if configured on LettuceConnectionFactory (enabled by default) across multiple LettuceClusterConnections. Connection sharing prevents creation and disposal of cluster connections per template command execution which improves overall performance.
Original Pull Request: #297
We now support SCAN commands with Redis Cluster. Cluster-wide scanning is supported with Lettuce only and SCAN on a selected node works with both clients.
// Lettuce only
Cursor<byte[]> scan = clusterConnection.scan(ScanOptions.NONE);
// Jedis and Lettuce
Cursor<byte[]> scan = clusterConnection.scan(new RedisClusterNode("127.0.0.1", 7379, SlotRange.empty()), ScanOptions.NONE);
Original Pull Request: #296
Rename incrementBy and decrementBy to increment respective decrement. Use INCR and DECR for increment() and decrement() instead of INCRBY 1/INCRYBY -1. Rearrange method order to align with method order in ReactiveValueOperations. Tweak Javadoc, add since tags.
Introduce increment() and decrement(…) (as of INCR/DECR) to ValueOperations and BoundValueOperations and use ValueOperations.increment()/decrement() from RedisAtomicInteger. ValueOperations used INCRBY and DECRBY to increment and now we use the native command if methods without delta are invoked.
Original pull request: #322.
We now support reactive execution of the following increment and decrement commands through ReactiveValueOperations:
- INCR
- INCRBY
- INCRBYFLOAT
- DECR
- DECRBY
Original pull request: #322.
We now support customization of type aliasing for types using through Redis Repositories. Type aliasing can be customized by either annotating types with @TypeAlias or by providing a RedisTypeMapper to MappingRedisConverter.
Map<Class<?>, String> mapping = new HashMap<>();
mapping.put(Person.class, "person");
ConfigurableTypeInformationMapper mapper = new ConfigurableTypeInformationMapper(mapping);
RedisTypeMapper typeMapper = new DefaultRedisTypeMapper(DefaultRedisTypeMapper.DEFAULT_TYPE_KEY, Collections.singletonList(mapper))
alternatively:
@RedisHash
@TypeAlias("person")
class Person {
// …
}
Original Pull Request: #299
We now export composable repositories through our CDI extension. Repositories can now be customized either by a single custom implementation (as it was before) and by providing fragment interfaces along their fragment implementation.
This change aligns CDI support with the existing RepositoryFactory support we provide within a Spring application context.
We now emit false when SET XX/SET NX complete without setting the value because the condition was evaluated to not set the value. Previously, we did not emit a value as Redis responds null (nil). This behavior becomes visible through ReactiveValueOperations.set[ifPresent|ifAbsent](…) methods.
This is a breaking change in the sense that changes the character of ReactiveValueOperations.set[ifPresent|ifAbsent](…) from an optionally emitted element to always emit. Reactive sequences that currently resume operation with .switchIfEmpty(…) will no longer utilize the fallback publisher.
Original pull request: #317.
We now support aggregation and weight options for ZINTERSTORE. We also encapsulate weights used for ZUNIONSTORE and ZINTERSTORE within a Weights value object.
zSetOps.intersectAndStore(set1, Arrays.asList(set2, set3), out, Aggregate.MAX,
Weights.of(1, 2, 1));
Related ticket: DATAREDIS-515.
Original Pull Request: #314
We now expose the underlying Redis Client instance via RedisClientProvider.getRedisClient() to components that require direct client interaction. The client is exposed through ClusterConnectionProvider and now also through LettucePoolingConnectionProvider.
Exposing the client via LettucePoolingConnectionProvider allows Redis Cluster usage with connection pooling.
Original Pull Request: #316
Added test with decimal and date map keys to verify those are flattened out correctly using the converters registered and updated documentation to point out limitation of map keys to simple types.
Original Pull Request: #312
We now consider the key type when reading a map from a Redis Hash. Previously, map keys were read as string while a map could declare numeric keys.
Original Pull Request: #312
Rename prefixKeysWith(CacheKeyPrefix) to computePrefixWith(…) and drop computePrefixWith(Function) in favor of CacheKeyPrefix. Refactor nullable keyPrefix to non-nullable. Extract default prefixing scheme to CacheKeyPrefix.simple().
Original pull request: #313.
We now allow, in addition to a static key prefix, the computation of prefixes based on the cache name. This change introduces an alternative to the in 2.x removed org.springframework.data.redis.cache.RedisCacheKey, and gives users more control over cache key generation.
Original pull request: #313.
We now provide a flag to disable the in flight cache creation for unconfigured caches. This gives eg. a CompositeCacheManager the possibility to chime in.
Original pull request: #311.
We now enable pool usage when configuring JedisConnectionFactory with RedisSentinelConfiguration to prevent accidental connections using the non-pooled standalone configuration. Jedis can operate with Sentinel only with pooling.
We also reject calls to disable pooling when JedisConnectionFactory is configured to use Sentinel.
Original Pull request: #307
We now order and assemble results of multi-key commands (e.g. MGET with cross-slot keys) that are executed on different nodes by positional keys to retain duplicate keys in the requested order and retain the server response.
Previously duplicate keys were treated as set of keys and the response didn't match the requested keys.
Original Pull Request: #303