40
40
import org .springframework .data .redis .connection .ReactiveSubscription .ChannelMessage ;
41
41
import org .springframework .data .redis .connection .ReactiveSubscription .Message ;
42
42
import org .springframework .data .redis .connection .ReactiveSubscription .PatternMessage ;
43
+ import org .springframework .data .redis .connection .SubscriptionListener ;
43
44
import org .springframework .data .redis .serializer .RedisElementReader ;
44
45
import org .springframework .data .redis .serializer .RedisSerializationContext .SerializationPair ;
45
46
import org .springframework .data .redis .serializer .RedisSerializer ;
@@ -178,21 +179,65 @@ public Flux<PatternMessage<String, String, String>> receive(PatternTopic... patt
178
179
}
179
180
180
181
/**
181
- * Subscribe to one or more {@link Topic}s and receive a stream of {@link ChannelMessage} The stream may contain
182
+ * Subscribe to one or more {@link Topic}s and receive a stream of {@link ChannelMessage}. The stream may contain
182
183
* {@link PatternMessage} if subscribed to patterns. Messages, and channel names are serialized/deserialized using the
183
184
* given {@code channelSerializer} and {@code messageSerializer}. The message stream subscribes lazily to the Redis
184
185
* channels and unsubscribes if the {@link org.reactivestreams.Subscription} is
185
186
* {@link org.reactivestreams.Subscription#cancel() cancelled}.
186
187
*
187
- * @param topics the channels to subscribe.
188
+ * @param topics the channels/patterns to subscribe.
189
+ * @param subscriptionListener listener to receive subscription/unsubscription notifications.
190
+ * @return the message stream.
191
+ * @throws InvalidDataAccessApiUsageException if {@code patternTopics} is empty.
192
+ * @see #receive(Iterable, SerializationPair, SerializationPair)
193
+ * @since 2.6
194
+ */
195
+ public Flux <Message <String , String >> receive (Iterable <? extends Topic > topics ,
196
+ SubscriptionListener subscriptionListener ) {
197
+ return receive (topics , stringSerializationPair , stringSerializationPair , subscriptionListener );
198
+ }
199
+
200
+ /**
201
+ * Subscribe to one or more {@link Topic}s and receive a stream of {@link ChannelMessage}. The stream may contain
202
+ * {@link PatternMessage} if subscribed to patterns. Messages, and channel names are serialized/deserialized using the
203
+ * given {@code channelSerializer} and {@code messageSerializer}. The message stream subscribes lazily to the Redis
204
+ * channels and unsubscribes if the {@link org.reactivestreams.Subscription} is
205
+ * {@link org.reactivestreams.Subscription#cancel() cancelled}.
206
+ *
207
+ * @param topics the channels/patterns to subscribe.
188
208
* @return the message stream.
189
209
* @see #receive(Iterable, SerializationPair, SerializationPair)
190
210
* @throws InvalidDataAccessApiUsageException if {@code topics} is empty.
191
211
*/
192
212
public <C , B > Flux <Message <C , B >> receive (Iterable <? extends Topic > topics , SerializationPair <C > channelSerializer ,
193
213
SerializationPair <B > messageSerializer ) {
214
+ return receive (topics , channelSerializer , messageSerializer , SubscriptionListener .EMPTY );
215
+ }
216
+
217
+ /**
218
+ * Subscribe to one or more {@link Topic}s and receive a stream of {@link ChannelMessage}. The stream may contain
219
+ * {@link PatternMessage} if subscribed to patterns. Messages, and channel names are serialized/deserialized using the
220
+ * given {@code channelSerializer} and {@code messageSerializer}. The message stream subscribes lazily to the Redis
221
+ * channels and unsubscribes if the {@link org.reactivestreams.Subscription} is
222
+ * {@link org.reactivestreams.Subscription#cancel() cancelled}. {@link SubscriptionListener} is notified upon
223
+ * subscription/unsubscription and can be used for synchronization.
224
+ *
225
+ * @param topics the channels to subscribe.
226
+ * @param channelSerializer
227
+ * @param messageSerializer
228
+ * @param subscriptionListener listener to receive subscription/unsubscription notifications.
229
+ * @return the message stream.
230
+ * @see #receive(Iterable, SerializationPair, SerializationPair)
231
+ * @throws InvalidDataAccessApiUsageException if {@code topics} is empty.
232
+ * @since 2.6
233
+ */
234
+ public <C , B > Flux <Message <C , B >> receive (Iterable <? extends Topic > topics , SerializationPair <C > channelSerializer ,
235
+ SerializationPair <B > messageSerializer , SubscriptionListener subscriptionListener ) {
194
236
195
237
Assert .notNull (topics , "Topics must not be null!" );
238
+ Assert .notNull (channelSerializer , "Channel serializer must not be null!" );
239
+ Assert .notNull (messageSerializer , "Message serializer must not be null!" );
240
+ Assert .notNull (subscriptionListener , "SubscriptionListener must not be null!" );
196
241
197
242
verifyConnection ();
198
243
@@ -203,7 +248,8 @@ public <C, B> Flux<Message<C, B>> receive(Iterable<? extends Topic> topics, Seri
203
248
throw new InvalidDataAccessApiUsageException ("No channels or patterns to subscribe to." );
204
249
}
205
250
206
- return doReceive (channelSerializer , messageSerializer , connection .pubSubCommands ().createSubscription (), patterns ,
251
+ return doReceive (channelSerializer , messageSerializer ,
252
+ connection .pubSubCommands ().createSubscription (subscriptionListener ), patterns ,
207
253
channels );
208
254
}
209
255
@@ -226,7 +272,7 @@ private <C, B> Flux<Message<C, B>> doReceive(SerializationPair<C> channelSeriali
226
272
Subscribers subscribers = getSubscribers (it );
227
273
if (subscribers .unregister ()) {
228
274
subscriptions .remove (it );
229
- it .unsubscribe ().subscribe (v -> terminalProcessor .onComplete (), terminalProcessor ::onError );
275
+ it .cancel ().subscribe (v -> terminalProcessor .onComplete (), terminalProcessor ::onError );
230
276
}
231
277
}).mergeWith (terminalProcessor );
232
278
});
0 commit comments