private synchronized Flux<ConsumerRecords<K, V>> createConsumerFlux() { if (consumerFlux != null) throw new IllegalStateException("Multiple subscribers are not supported for KafkaReceiver flux"); Consumer<Flux<?>> kafkaSubscribeOrAssign = (flux) -> receiverOptions.subscriber(this).accept(consumer); initEvent = new InitEvent(kafkaSubscribeOrAssign); pollEvent = new PollEvent(); commitEvent = new CommitEvent(); recordEmitter = EmitterProcessor.create(); recordSubmission = recordEmitter.sink(); scheduler = Schedulers.single(receiverOptions.schedulerSupplier().get()); consumerFlux = recordEmitter .publishOn(scheduler) .doOnSubscribe(s -> { try { start(); } catch (Exception e) { log.error("Subscription to event flux failed", e); throw e; } }) .doOnRequest(r -> { if (requestsPending.get() > 0) pollEvent.scheduleIfRequired(); }) .doAfterTerminate(this::dispose) .doOnCancel(this::dispose); return consumerFlux; }
private synchronized Flux<ConsumerRecords<K, V>> createConsumerFlux() { if (consumerFlux != null) throw new IllegalStateException("Multiple subscribers are not supported for KafkaReceiver flux"); Consumer<Flux<?>> kafkaSubscribeOrAssign = (flux) -> receiverOptions.subscriber(this).accept(consumer); initEvent = new InitEvent(kafkaSubscribeOrAssign); pollEvent = new PollEvent(); commitEvent = new CommitEvent(); recordEmitter = EmitterProcessor.create(); recordSubmission = recordEmitter.sink(); scheduler = Schedulers.single(receiverOptions.schedulerSupplier().get()); consumerFlux = recordEmitter .publishOn(scheduler) .doOnSubscribe(s -> { try { start(); } catch (Exception e) { log.error("Subscription to event flux failed", e); throw e; } }) .doOnRequest(r -> { if (requestsPending.get() > 0) pollEvent.scheduleIfRequired(); }) .doAfterTerminate(this::dispose) .doOnCancel(this::dispose); return consumerFlux; }
@Test public void publishFromEventScheduler() throws Exception { receiverOptions = receiverOptions .schedulerSupplier(Schedulers::immediate) .addAssignListener(this::onPartitionsAssigned) .subscription(Collections.singletonList(topic)); KafkaReceiver<Integer, String> receiver = KafkaReceiver.create(receiverOptions); AtomicReference<String> publishingThreadName = new AtomicReference<>(); CountDownLatch receiveLatch = new CountDownLatch(1); Disposable disposable = receiver.receive() .doOnNext(record -> { publishingThreadName.set(Thread.currentThread().getName()); record.receiverOffset().acknowledge(); receiveLatch.countDown(); }) .subscribe(); subscribeDisposables.add(disposable); waitFoPartitionAssignment(); sendMessages(0, 1); waitForMessages(receiveLatch); assertNotNull(publishingThreadName.get()); assertTrue(publishingThreadName.get().startsWith("reactive-kafka-")); }
@Test public void publishFromCustomScheduler() throws Exception { String schedulerName = "custom-scheduler"; Scheduler scheduler = Schedulers.newElastic(schedulerName); receiverOptions = receiverOptions .schedulerSupplier(() -> scheduler) .addAssignListener(this::onPartitionsAssigned) .subscription(Collections.singletonList(topic)); KafkaReceiver<Integer, String> receiver = KafkaReceiver.create(receiverOptions); AtomicReference<String> publishingThreadName = new AtomicReference<>(); CountDownLatch receiveLatch = new CountDownLatch(1); Disposable disposable = receiver.receive() .doOnNext(record -> { publishingThreadName.set(Thread.currentThread().getName()); record.receiverOffset().acknowledge(); receiveLatch.countDown(); }) .subscribe(); subscribeDisposables.add(scheduler); subscribeDisposables.add(disposable); waitFoPartitionAssignment(); sendMessages(0, 1); waitForMessages(receiveLatch); assertNotNull(publishingThreadName.get()); assertTrue(publishingThreadName.get().startsWith(schedulerName)); }
ImmutableReceiverOptions(ReceiverOptions<K, V> options) { this( options.consumerProperties(), options.assignListeners(), options.revokeListeners(), options.keyDeserializer(), options.valueDeserializer(), options.pollTimeout(), options.closeTimeout(), options.commitInterval(), options.commitBatchSize(), options.atmostOnceCommitAheadSize(), options.maxCommitAttempts(), options.subscriptionTopics(), options.assignment(), options.subscriptionPattern(), options.schedulerSupplier() ); }
ImmutableReceiverOptions(ReceiverOptions<K, V> options) { this( options.consumerProperties(), options.assignListeners(), options.revokeListeners(), options.keyDeserializer(), options.valueDeserializer(), options.pollTimeout(), options.closeTimeout(), options.commitInterval(), options.commitBatchSize(), options.atmostOnceCommitAheadSize(), options.maxCommitAttempts(), options.subscriptionTopics(), options.assignment(), options.subscriptionPattern(), options.schedulerSupplier() ); }