From d356ade624649a699bc4831be129ef20ad6eb9cf Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 26 Apr 2018 09:18:44 +0200 Subject: [PATCH] DATAREDIS-612 - Documentation. Original Pull Request: #295 --- src/main/asciidoc/new-features.adoc | 1 + .../reference/reactive-messaging.adoc | 57 +++++++++++++++++++ .../asciidoc/reference/reactive-redis.adoc | 2 + 3 files changed, 60 insertions(+) create mode 100644 src/main/asciidoc/reference/reactive-messaging.adoc diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 3f2451437..aebfa70af 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -11,6 +11,7 @@ New and noteworthy in the latest releases. * <> integration. * `@TypeAlias` Support for Redis repositories. * Cluster-wide `SCAN` using Lettuce and `SCAN` execution on a selected node supported by both drivers. +* <> to send and receive a message stream. [[new-in-2.0.0]] == New in Spring Data Redis 2.0 diff --git a/src/main/asciidoc/reference/reactive-messaging.adoc b/src/main/asciidoc/reference/reactive-messaging.adoc new file mode 100644 index 000000000..9a871aa6d --- /dev/null +++ b/src/main/asciidoc/reference/reactive-messaging.adoc @@ -0,0 +1,57 @@ +[[redis:reactive:pubsub]] += Redis Messaging/PubSub + +Spring Data provides dedicated messaging integration for Redis, very similar in functionality and naming to the JMS integration in Spring Framework; in fact, users familiar with the JMS support in Spring should feel right at home. + +Redis messaging can be roughly divided into two areas of functionality, namely the production or publication and consumption or subscription of messages, hence the shortcut pubsub (Publish/Subscribe). The `ReactiveRedisTemplate` class is used for message production. For asynchronous reception, Spring Data provides a dedicated message listener container that is used consume a stream of messages. + +The package `org.springframework.data.redis.connection` and `org.springframework.data.redis.listener` provide the core functionality for using Redis messaging. + +[[redis:reactive:pubsub:publish]] +== Sending/Publishing messages + +To publish a message, one can use, as with the other operations, either the low-level `ReactiveRedisConnection` or the high-level `ReactiveRedisTemplate`. Both entities offer a publish method that accepts as an argument the message that needs to be sent as well as the destination channel. While `ReactiveRedisConnection` requires raw-data, the `ReactiveRedisTemplate` allow arbitrary objects to be passed in as messages: + +[source,java] +---- +// send message through ReactiveRedisConnection +ByteBuffer msg = … +ByteBuffer channel = … +Mono publish = con.publish(msg, channel); + +// send message through ReactiveRedisTemplate +ReactiveRedisTemplate template = … +Mono publish = template.convertAndSend("hello!", "world"); +---- + +[[redis:reactive:pubsub:subscribe]] +== Receiving/Subscribing for messages + +On the receiving side, one can subscribe to one or multiple channels either by naming them directly or by using pattern matching. The latter approach is quite useful as it not only allows multiple subscriptions to be created with one command but to also listen on channels not yet created at subscription time (as long as they match the pattern). + +At the low-level, `ReactiveRedisConnection` offers `subscribe` and `pSubscribe` methods that map the Redis commands for subscribing by channel respectively by pattern. Note that multiple channels or patterns can be used as arguments. To change a subscription, simply query the channels and patterns of `ReactiveSubscription`. + +NOTE: Reactive subscription commands in Spring Data Redis non-blocking and terminate without emitting an element. + +As mentioned above, once subscribed a connection starts waiting for messages. No other commands can be invoked on it except for adding new subscriptions or modifying/canceling the existing ones. Commands other than `subscribe`, `pSubscribe`, `unsubscribe`, or `pUnsubscribe` are illegal and will cause an exception. + +In order to receive messages, one needs to obtain the message stream. Note that a subscription only publishes messages for channels and patterns that are registered with that particular subscription. The message stream itself is a hot sequence that produces elements without regard to demand. Make sure to register sufficient demand to not exhaust the message buffer. + +[[redis:reactive:pubsub:subscribe:containers]] +=== Message Listener Containers + +Spring Data offers `ReactiveRedisMessageListenerContainer` which does all the heavy lifting of conversion and subscription state management on behalf of the user. + +`ReactiveRedisMessageListenerContainer` acts as a message listener container; it is used to receive messages from a Redis channel and expose a stream of messages that emits channel messages with deserialization applied. It takes care of registering to receive messages, resource acquisition and release, exception conversion and the like. This allows you as an application developer to write the (possibly complex) business logic associated with receiving a message (and reacting to it), and delegates boilerplate Redis infrastructure concerns to the framework. Message streams register a subscription in Redis upon publisher subscription and unregister if the subscription gets canceled. + +Furthermore, to minimize the application footprint, `ReactiveRedisMessageListenerContainer` allows one connection and one thread to be shared by multiple listeners even though they do not share a subscription. Thus no matter how many listeners or channels an application tracks, the runtime cost will remain the same through out its lifetime. Moreover, the container allows runtime configuration changes so one can add or remove listeners while an application is running without the need for restart. Additionally, the container uses a lazy subscription approach, using a `ReactiveRedisConnection` only when needed - if all the listeners are unsubscribed, cleanup is automatically performed. + +The message listener container itself does not require external threading resources. It uses the driver threads to publish messages. + +[source,java] +---- +ReactiveRedisConnectionFactory factory = … +ReactiveRedisMessageListenerContainer container = new ReactiveRedisMessageListenerContainer(factory); + +Flux> stream = container.receive(new ChannelTopic("my-chanel")); +---- diff --git a/src/main/asciidoc/reference/reactive-redis.adoc b/src/main/asciidoc/reference/reactive-redis.adoc index 7d3913f60..35040b89f 100644 --- a/src/main/asciidoc/reference/reactive-redis.adoc +++ b/src/main/asciidoc/reference/reactive-redis.adoc @@ -161,6 +161,8 @@ public class Example { } ---- +include::{referenceDir}/reactive-messaging.adoc[leveloffset=+1] + == Reactive Scripting Executing Redis scripts via the reactive infrastructure can be done using the `ReactiveScriptExecutor` accessed best via `ReactiveRedisTemplate`.