All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.messaging.eventhubs.SynchronousPartitionReceiver Maven / Gradle / Ivy

There is a newer version: 5.19.2
Show newest version
// 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