com.azure.messaging.eventhubs.SynchronousPartitionReceiver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of azure-messaging-eventhubs Show documentation
Show all versions of azure-messaging-eventhubs Show documentation
Libraries built on Microsoft Azure Event Hubs
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.messaging.eventhubs;
import com.azure.core.amqp.implementation.WindowedSubscriber;
import com.azure.core.amqp.implementation.WindowedSubscriber.WindowedSubscriberOptions;
import com.azure.core.util.IterableStream;
import com.azure.messaging.eventhubs.implementation.instrumentation.EventHubsConsumerInstrumentation;
import com.azure.messaging.eventhubs.models.EventPosition;
import com.azure.messaging.eventhubs.models.PartitionEvent;
import com.azure.messaging.eventhubs.models.ReceiveOptions;
import reactor.core.publisher.Flux;
import java.time.Duration;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import static com.azure.messaging.eventhubs.implementation.ClientConstants.PARTITION_ID_KEY;
/**
* A type that channels synchronous receive requests to a backing asynchronous receiver client.
*/
final class SynchronousPartitionReceiver {
private static final String TERMINAL_MESSAGE = "The receiver client is terminated. Re-create the client to continue receive attempt.";
private final EventHubsConsumerInstrumentation instrumentation;
private final AtomicReference receiver = new AtomicReference<>(null);
/**
* Creates a SynchronousPartitionReceiver.
*
* @param client the backing asynchronous client to connect to the broker, delegate message requesting and receive.
*/
SynchronousPartitionReceiver(EventHubConsumerAsyncClient client) {
Objects.requireNonNull(client, "'client' cannot be null.");
this.receiver.set(new DelegatingReceiver(client));
this.instrumentation = client.getInstrumentation();
}
/**
* Request a specified number of event from a parition and obtain an {@link IterableStream} streaming the received
* event.
*
* @param partitionId Identifier of the partition to read events from.
* @param startingPosition Position within the Event Hub partition to begin consuming events.
* @param receiveOptions Options when receiving events from the partition.
* @param maxEvents the maximum number of event to receive.
* @param maxWaitTime the upper bound for the time to wait to receive the requested number of event.
*
* @return an {@link IterableStream} of at most {@code maxEvents} event.
*/
IterableStream receive(String partitionId, EventPosition startingPosition,
ReceiveOptions receiveOptions, int maxEvents, Duration maxWaitTime) {
Objects.requireNonNull(partitionId, "'partitionId' cannot be null.");
Objects.requireNonNull(startingPosition, "'startingPosition' cannot be null.");
Objects.requireNonNull(receiveOptions, "'receiveOptions' cannot be null.");
final WindowedSubscriber subscriber = createSubscriber(partitionId);
final Flux upstream = receiver.get().receive(partitionId, startingPosition, receiveOptions);
upstream.subscribeWith(subscriber);
final Flux windowFlux = subscriber.enqueueRequestFlux(maxEvents, maxWaitTime);
return new IterableStream<>(windowFlux.doOnComplete(subscriber::cancel).doOnError(__ -> subscriber.cancel()));
}
/**
* Disposes the SynchronousReceiver.
*
* Once disposed, the {@link IterableStream} for any future or pending receive requests will receive terminated error.
*
*/
void dispose() {
receiver.set(Receiver.DISPOSED);
}
/**
* Create a {@link WindowedSubscriber} capable of bridging synchronous receive requests to an upstream of
* asynchronous event.
*
* @param partitionId Identifier of the partition to read events from.
*
* @return The subscriber.
*/
private WindowedSubscriber createSubscriber(String partitionId) {
final WindowedSubscriberOptions options = new WindowedSubscriberOptions<>();
options.setWindowDecorator(toDecorate -> {
// Decorates the provided 'toDecorate' flux for tracing the signals (events, termination) it produces.
return instrumentation.syncReceive(toDecorate, partitionId);
});
return new WindowedSubscriber<>(Collections.singletonMap(PARTITION_ID_KEY, partitionId), TERMINAL_MESSAGE, options);
}
private interface Receiver {
Receiver DISPOSED = (partitionId, startingPosition, receiveOptions) -> Flux.error(new RuntimeException(TERMINAL_MESSAGE));
Flux receive(String partitionId, EventPosition startingPosition, ReceiveOptions receiveOptions);
}
private static final class DelegatingReceiver implements Receiver {
private final EventHubConsumerAsyncClient client;
DelegatingReceiver(EventHubConsumerAsyncClient client) {
this.client = Objects.requireNonNull(client, "'client' cannot be null.");
}
@Override
public Flux receive(String partitionId, EventPosition startingPosition, ReceiveOptions receiveOptions) {
assert client.isV2();
return client.receiveFromPartition(partitionId, startingPosition, receiveOptions);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy