diff --git a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml index 7891958977f8..729e49272d96 100755 --- a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml +++ b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml @@ -363,6 +363,7 @@ the main ServiceBusClientBuilder. --> + diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerAsyncClient.java new file mode 100644 index 000000000000..3e137a0e3c62 --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerAsyncClient.java @@ -0,0 +1,320 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.messaging.eventhubs; + +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceClient; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.util.logging.ClientLogger; +import com.azure.messaging.eventhubs.models.SendBatchFailedContext; +import com.azure.messaging.eventhubs.models.SendBatchSucceededContext; +import com.azure.messaging.eventhubs.models.SendOptions; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.Closeable; +import java.time.Duration; +import java.util.HashMap; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.function.Consumer; + +/** + * A client responsible for publishing instances of {@link EventData} to a specific Event Hub. Depending on the options + * specified when events are enqueued, they may be automatically assigned to a partition, grouped according to the + * specified partition key, or assigned a specifically requested partition. + * + *

+ * The {@link EventHubBufferedProducerAsyncClient} does not publish immediately, instead using a deferred model where + * events are collected into a buffer so that they may be efficiently batched and published when the batch is full or + * the {@link EventHubBufferedProducerClientBuilder#maxWaitTime(Duration) maxWaitTime} has elapsed with no new events + * enqueued. + *

+ *

+ * This model is intended to shift the burden of batch management from callers, at the cost of non-deterministic timing, + * for when events will be published. There are additional trade-offs to consider, as well: + *

+ *
    + *
  • If the application crashes, events in the buffer will not have been published. To + * prevent data loss, callers are encouraged to track publishing progress using + * {@link EventHubBufferedProducerClientBuilder#onSendBatchFailed(Consumer) onSendBatchFailed} and + * {@link EventHubBufferedProducerClientBuilder#onSendBatchSucceeded(Consumer) onSendBatchSucceeded}.
  • + *
  • Events specifying a partition key may be assigned a different partition than those + * using the same key with other producers.
  • + *
  • In the unlikely event that a partition becomes temporarily unavailable, + * the {@link EventHubBufferedProducerAsyncClient} may take longer to recover than other producers.
  • + *
+ *

+ * In scenarios where it is important to have events published immediately with a deterministic outcome, ensure that + * partition keys are assigned to a partition consistent with other publishers, or where maximizing availability is a + * requirement, using {@link EventHubProducerAsyncClient} or {@link EventHubProducerClient} is recommended. + *

+ */ +@ServiceClient(builder = EventHubBufferedProducerClientBuilder.class, isAsync = true) +public final class EventHubBufferedProducerAsyncClient implements Closeable { + private final ClientLogger logger = new ClientLogger(EventHubBufferedProducerAsyncClient.class); + private final EventHubAsyncClient client; + private final EventHubClientBuilder builder; + private final BufferedProducerClientOptions clientOptions; + + // Key: partitionId. + private final HashMap> partitionBatchMap = new HashMap<>(); + private final Mono initialisationMono; + + EventHubBufferedProducerAsyncClient(EventHubClientBuilder builder, BufferedProducerClientOptions clientOptions) { + this.builder = builder; + this.client = builder.buildAsyncClient(); + this.clientOptions = clientOptions; + + initialisationMono = Mono.using( + () -> builder.buildAsyncClient(), + eventHubClient -> eventHubClient.getPartitionIds() + .handle((partitionId, sink) -> { + try { + partitionBatchMap.put(partitionId, new ConcurrentLinkedDeque<>()); + sink.complete(); + } catch (Exception e) { + sink.error(e); + } + }).then(), + eventHubClient -> eventHubClient.close()); + } + + /** + * Gets the fully qualified Event Hubs namespace that the connection is associated with. This is likely similar to + * {@code {yournamespace}.servicebus.windows.net}. + * + * @return The fully qualified Event Hubs namespace that the connection is associated with + */ + public String getFullyQualifiedNamespace() { + return client.getFullyQualifiedNamespace(); + } + + /** + * Gets the Event Hub name this client interacts with. + * + * @return The Event Hub name this client interacts with. + */ + public String getEventHubName() { + return client.getEventHubName(); + } + + /** + * Retrieves information about an Event Hub, including the number of partitions present and their identifiers. + * + * @return The set of information for the Event Hub that this client is associated with. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono getEventHubProperties() { + return client.getProperties(); + } + + /** + * Retrieves the identifiers for the partitions of an Event Hub. + * + * @return A Flux of identifiers for the partitions of an Event Hub. + */ + @ServiceMethod(returns = ReturnType.COLLECTION) + public Flux getPartitionIds() { + return client.getPartitionIds(); + } + + /** + * Retrieves information about a specific partition for an Event Hub, including elements that describe the available + * events in the partition event stream. + * + * @param partitionId The unique identifier of a partition associated with the Event Hub. + * + * @return The set of information for the requested partition under the Event Hub this client is associated with. + * + * @throws NullPointerException if {@code partitionId} is null. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono getPartitionProperties(String partitionId) { + return client.getPartitionProperties(partitionId); + } + + /** + * Gets the total number of events that are currently buffered and waiting to be published, across all partitions. + * + * @return The total number of events that are currently buffered and waiting to be published, across all + * partitions. + */ + public int getBufferedEventCount() { + return 0; + } + + /** + * Gets the number of events that are buffered and waiting to be published for a given partition. + * + * @param partitionId The partition identifier. + * + * @return The number of events that are buffered and waiting to be published for a given partition. + */ + public int getBufferedEventCount(String partitionId) { + return 0; + } + + /** + * Enqueues an {@link EventData} into the buffer to be published to the Event Hub. If there is no capacity in the + * buffer when this method is invoked, it will wait for space to become available and ensure that the {@code + * eventData} has been enqueued. + * + * When this call returns, the {@code eventData} has been accepted into the buffer, but it may not have been + * published yet. Publishing will take place at a nondeterministic point in the future as the buffer is processed. + * + * @param eventData The event to be enqueued into the buffer and, later, published. + * + * @return The total number of events that are currently buffered and waiting to be published, across all + * partitions. + */ + public Mono enqueueEvent(EventData eventData) { + return null; + } + + /** + * Enqueues an {@link EventData} into the buffer to be published to the Event Hub. If there is no capacity in the + * buffer when this method is invoked, it will wait for space to become available and ensure that the {@code + * eventData} has been enqueued. + * + * When this call returns, the {@code eventData} has been accepted into the buffer, but it may not have been + * published yet. Publishing will take place at a nondeterministic point in the future as the buffer is processed. + * + * @param eventData The event to be enqueued into the buffer and, later, published. + * @param options The set of options to apply when publishing this event. + * + * @return The total number of events that are currently buffered and waiting to be published, across all + * partitions. + */ + public Mono enqueueEvent(EventData eventData, SendOptions options) { + return null; + } + + /** + * Enqueues a set of {@link EventData} into the buffer to be published to the Event Hub. If there is insufficient + * capacity in the buffer when this method is invoked, it will wait for space to become available and ensure that + * all EventData in the {@code events} set have been enqueued. + * + * When this call returns, the {@code events} have been accepted into the buffer, but it may not have been published + * yet. Publishing will take place at a nondeterministic point in the future as the buffer is processed. + * + * @param events The set of events to be enqueued into the buffer and, later, published. + * + * @return The total number of events that are currently buffered and waiting to be published, across all + * partitions. + */ + public Mono enqueueEvents(Iterable events) { + return null; + } + + /** + * Enqueues a set of {@link EventData} into the buffer to be published to the Event Hub. If there is insufficient + * capacity in the buffer when this method is invoked, it will wait for space to become available and ensure that + * all EventData in the {@code events} set have been enqueued. + * + * When this call returns, the {@code events} have been accepted into the buffer, but it may not have been published + * yet. Publishing will take place at a nondeterministic point in the future as the buffer is processed. + * + * @param events The set of events to be enqueued into the buffer and, later, published. + * @param options The set of options to apply when publishing this event. + * + * @return The total number of events that are currently buffered and waiting to be published, across all + * partitions. + */ + public Mono enqueueEvents(Iterable events, SendOptions options) { + return null; + } + + /** + * Attempts to publish all events in the buffer immediately. This may result in multiple batches being published, + * the outcome of each of which will be individually reported by the + * {@link EventHubBufferedProducerClientBuilder#onSendBatchFailed(Consumer)} + * and {@link EventHubBufferedProducerClientBuilder#onSendBatchSucceeded(Consumer)} handlers. + * + * Upon completion of this method, the buffer will be empty. + * + * @return A mono that completes when the buffers are empty. + */ + public Mono flush() { + return null; + } + + /** + * Disposes of the producer and all its resources. + */ + @Override + public void close() { + client.close(); + } + + /** + * A set of options to pass when creating the {@link EventHubBufferedProducerClient} or {@link + * EventHubBufferedProducerAsyncClient}. + */ + static class BufferedProducerClientOptions { + private boolean enableIdempotentRetries = false; + private int maxConcurrentSendsPerPartition = 1; + + private int maxPendingEventCount = 1500; + private Duration maxWaitTime; + private Consumer sendFailedContext; + private Consumer sendSucceededContext; + private int maxConcurrentSends; + + boolean isEnableIdempotentRetries() { + return enableIdempotentRetries; + } + + void setEnableIdempotentRetries(boolean enableIdempotentRetries) { + this.enableIdempotentRetries = enableIdempotentRetries; + } + + int getMaxConcurrentSends() { + return maxConcurrentSends; + } + + void setMaxConcurrentSends(int maxConcurrentSends) { + this.maxConcurrentSends = maxConcurrentSends; + } + + int getMaxConcurrentSendsPerPartition() { + return maxConcurrentSendsPerPartition; + } + + void setMaxConcurrentSendsPerPartition(int maxConcurrentSendsPerPartition) { + this.maxConcurrentSendsPerPartition = maxConcurrentSendsPerPartition; + } + + int getMaxPendingEventCount() { + return maxPendingEventCount; + } + + void setMaxPendingEventCount(int maxPendingEventCount) { + this.maxPendingEventCount = maxPendingEventCount; + } + + Duration getMaxWaitTime() { + return this.maxWaitTime; + } + + void setMaxWaitTime(Duration maxWaitTime) { + this.maxWaitTime = maxWaitTime; + } + + Consumer getSendFailedContext() { + return sendFailedContext; + } + + void setSendFailedContext(Consumer sendFailedContext) { + this.sendFailedContext = sendFailedContext; + } + + Consumer getSendSucceededContext() { + return sendSucceededContext; + } + + void setSendSucceededContext(Consumer sendSucceededContext) { + this.sendSucceededContext = sendSucceededContext; + } + } +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerClient.java new file mode 100644 index 000000000000..521078c0bf64 --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerClient.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.messaging.eventhubs; + + +import com.azure.core.annotation.ServiceClient; + +import java.time.Duration; +import java.util.function.Consumer; + +/** + * A client responsible for publishing instances of {@link EventData} to a specific Event Hub. Depending on the options + * specified when events are enqueued, they may be automatically assigned to a partition, grouped according to the + * specified partition key, or assigned a specifically requested partition. + * + *

+ * The {@link EventHubBufferedProducerClient} does not publish immediately, instead using a deferred model where + * events are collected into a buffer so that they may be efficiently batched and published when the batch is full or + * the {@link EventHubBufferedProducerClientBuilder#maxWaitTime(Duration) maxWaitTime} has elapsed with no new events + * enqueued. + *

+ *

+ * This model is intended to shift the burden of batch management from callers, at the cost of non-deterministic timing, + * for when events will be published. There are additional trade-offs to consider, as well: + *

+ *
    + *
  • If the application crashes, events in the buffer will not have been published. To + * prevent data loss, callers are encouraged to track publishing progress using + * {@link EventHubBufferedProducerClientBuilder#onSendBatchFailed(Consumer) onSendBatchFailed} and + * {@link EventHubBufferedProducerClientBuilder#onSendBatchSucceeded(Consumer) onSendBatchSucceeded}.
  • + *
  • Events specifying a partition key may be assigned a different partition than those + * using the same key with other producers.
  • + *
  • In the unlikely event that a partition becomes temporarily unavailable, + * the {@link EventHubBufferedProducerClient} may take longer to recover than other producers.
  • + *
+ *

+ * In scenarios where it is important to have events published immediately with a deterministic outcome, ensure that + * partition keys are assigned to a partition consistent with other publishers, or where maximizing availability is a + * requirement, using {@link EventHubProducerAsyncClient} or {@link EventHubProducerClient} is recommended. + *

+ */ +@ServiceClient(builder = EventHubBufferedProducerClientBuilder.class, isAsync = false) +public final class EventHubBufferedProducerClient { +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerClientBuilder.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerClientBuilder.java new file mode 100644 index 000000000000..0c7dfeba650a --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubBufferedProducerClientBuilder.java @@ -0,0 +1,374 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.messaging.eventhubs; + +import com.azure.core.amqp.AmqpRetryOptions; +import com.azure.core.amqp.AmqpTransportType; +import com.azure.core.amqp.ProxyOptions; +import com.azure.core.annotation.ServiceClientBuilder; +import com.azure.core.annotation.ServiceClientProtocol; +import com.azure.core.credential.AzureNamedKeyCredential; +import com.azure.core.credential.AzureSasCredential; +import com.azure.core.credential.TokenCredential; +import com.azure.core.exception.AzureException; +import com.azure.core.util.ClientOptions; +import com.azure.core.util.Configuration; +import com.azure.messaging.eventhubs.models.SendBatchFailedContext; +import com.azure.messaging.eventhubs.models.SendBatchSucceededContext; + +import java.net.URL; +import java.time.Duration; +import java.util.function.Consumer; + +import static com.azure.messaging.eventhubs.EventHubBufferedProducerAsyncClient.BufferedProducerClientOptions; + +/** + * Builder used to instantiate {@link EventHubBufferedProducerClient} and {@link EventHubBufferedProducerAsyncClient}. + * + * @see EventHubBufferedProducerClient + * @see EventHubBufferedProducerAsyncClient + */ +@ServiceClientBuilder( + serviceClients = {EventHubBufferedProducerAsyncClient.class, EventHubBufferedProducerClient.class}, + protocol = ServiceClientProtocol.AMQP) +public final class EventHubBufferedProducerClientBuilder { + private final EventHubClientBuilder builder; + private final BufferedProducerClientOptions clientOptions = new BufferedProducerClientOptions(); + + /** + * Creates a new instance with the default transport {@link AmqpTransportType#AMQP}. + */ + public EventHubBufferedProducerClientBuilder() { + builder = new EventHubClientBuilder(); + } + + /** + * Sets the client options. + * + * @param clientOptions The client options. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder clientOptions(ClientOptions clientOptions) { + builder.clientOptions(clientOptions); + return this; + } + + /** + * Sets the configuration store that is used during construction of the service client. + * + * If not specified, the default configuration store is used to configure the buffered producer. Use {@link + * Configuration#NONE} to bypass using configuration settings during construction. + * + * @param configuration The configuration store used to configure the buffered producer. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder configuration(Configuration configuration) { + builder.configuration(configuration); + return this; + } + + /** + * Sets the credential information given a connection string to the Event Hub instance. + * + *

+ * If the connection string is copied from the Event Hubs namespace, it will likely not contain the name to the + * desired Event Hub, which is needed. In this case, the name can be added manually by adding {@literal + * "EntityPath=EVENT_HUB_NAME"} to the end of the connection string. For example, "EntityPath=telemetry-hub". + *

+ * + *

+ * If you have defined a shared access policy directly on the Event Hub itself, then copying the connection string + * from that Event Hub will result in a connection string that contains the name. + *

+ * + * @param connectionString The connection string to use for connecting to the Event Hub instance. It is expected + * that the Event Hub name and the shared access key properties are contained in this connection string. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + * + * @throws IllegalArgumentException if {@code connectionString} is null or empty. Or, the {@code + * connectionString} does not contain the "EntityPath" key, which is the name of the Event Hub instance. + * @throws AzureException If the shared access signature token credential could not be created using the + * connection string. + */ + public EventHubBufferedProducerClientBuilder connectionString(String connectionString) { + builder.connectionString(connectionString); + return this; + } + + /** + * Sets the credential information given a connection string to the Event Hubs namespace and name to a specific + * Event Hub instance. + * + * @param connectionString The connection string to use for connecting to the Event Hubs namespace; it is + * expected that the shared access key properties are contained in this connection string, but not the Event Hub + * name. + * @param eventHubName The name of the Event Hub to connect the client to. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + * + * @throws NullPointerException if {@code connectionString} or {@code eventHubName} is null. + * @throws IllegalArgumentException if {@code connectionString} or {@code eventHubName} is an empty string. Or, + * if the {@code connectionString} contains the Event Hub name. + * @throws AzureException If the shared access signature token credential could not be created using the + * connection string. + */ + public EventHubBufferedProducerClientBuilder connectionString(String connectionString, String eventHubName) { + builder.connectionString(connectionString, eventHubName); + return this; + } + + /** + * Sets the credential information for which Event Hub instance to connect to, and how to authorize against it. + * + * @param fullyQualifiedNamespace The fully qualified name for the Event Hubs namespace. This is likely to be + * similar to {@literal "{your-namespace}.servicebus.windows.net}". + * @param eventHubName The name of the Event Hub to connect the client to. + * @param credential The token credential to use for authorization. Access controls may be specified by the + * Event Hubs namespace or the requested Event Hub, depending on Azure configuration. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + * + * @throws IllegalArgumentException if {@code fullyQualifiedNamespace} or {@code eventHubName} is an empty + * string. + * @throws NullPointerException if {@code fullyQualifiedNamespace}, {@code eventHubName}, or {@code credential} + * is null. + */ + public EventHubBufferedProducerClientBuilder credential(String fullyQualifiedNamespace, String eventHubName, + TokenCredential credential) { + builder.credential(fullyQualifiedNamespace, eventHubName, credential); + return this; + } + + /** + * Sets the {@link TokenCredential} used to authorize requests sent to the service. Refer to the Azure SDK for Java + * identity and authentication documentation for more details + * on proper usage of the {@link TokenCredential} type. + * + * @param fullyQualifiedNamespace The fully qualified name for the Event Hubs namespace. This is likely to be + * similar to {@literal "{your-namespace}.servicebus.windows.net}". + * @param eventHubName The name of the Event Hub to connect the client to. + * @param credential The token credential to use for authorization. Access controls may be specified by the + * Event Hubs namespace or the requested Event Hub, depending on Azure configuration. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + * + * @throws NullPointerException if {@code fullyQualifiedNamespace}, {@code eventHubName}, or {@code credential} + * is null. + */ + public EventHubBufferedProducerClientBuilder credential(String fullyQualifiedNamespace, String eventHubName, + AzureNamedKeyCredential credential) { + builder.credential(fullyQualifiedNamespace, eventHubName, credential); + return this; + } + + /** + * Sets the {@link TokenCredential} used to authorize requests sent to the service. Refer to the Azure SDK for Java + * identity and authentication documentation for more details + * on proper usage of the {@link TokenCredential} type. + * + * @param fullyQualifiedNamespace The fully qualified name for the Event Hubs namespace. This is likely to be + * similar to {@literal "{your-namespace}.servicebus.windows.net}". + * @param eventHubName The name of the Event Hub to connect the client to. + * @param credential The token credential to use for authorization. Access controls may be specified by the + * Event Hubs namespace or the requested Event Hub, depending on Azure configuration. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + * + * @throws NullPointerException if {@code fullyQualifiedNamespace}, {@code eventHubName}, or {@code credential} + * is null. + */ + public EventHubBufferedProducerClientBuilder credential(String fullyQualifiedNamespace, String eventHubName, + AzureSasCredential credential) { + builder.credential(fullyQualifiedNamespace, eventHubName, credential); + return this; + } + + /** + * Sets a custom endpoint address when connecting to the Event Hubs service. This can be useful when your network + * does not allow connecting to the standard Azure Event Hubs endpoint address, but does allow connecting through an + * intermediary. For example: {@literal https://my.custom.endpoint.com:55300}. + *

+ * If no port is specified, the default port for the {@link #transportType(AmqpTransportType) transport type} is + * used. + * + * @param customEndpointAddress The custom endpoint address. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + * + * @throws IllegalArgumentException if {@code customEndpointAddress} cannot be parsed into a valid {@link URL}. + */ + public EventHubBufferedProducerClientBuilder customEndpointAddress(String customEndpointAddress) { + builder.customEndpointAddress(customEndpointAddress); + return this; + } + + /** + * Indicates whether events should be published using idempotent semantics for retries. If enabled, retries during + * publishing will attempt to avoid duplication with a minor cost to throughput. Duplicates are still possible but + * the chance of them occurring is much lower when idempotent retries are enabled. + * + *

+ * It is important to note that enabling idempotent retries does not guarantee exactly-once semantics. The existing + * Event Hubs at-least-once delivery contract still applies and event duplication is unlikely, but possible. + *

+ * + * @param enableIdempotentRetries {@code true} to enable idempotent retries, {@code false} otherwise. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder enableIdempotentRetries(boolean enableIdempotentRetries) { + clientOptions.setEnableIdempotentRetries(enableIdempotentRetries); + return this; + } + + /** + * The total number of batches that may be sent concurrently, across all partitions. This limit takes precedence + * over the value specified in {@link #maxConcurrentSendsPerPartition(int) maxConcurrentSendsPerPartition}, ensuring + * this maximum is respected. When batches for the same partition are published concurrently, the ordering of + * events is not guaranteed. If the order events are published must be maintained, + * {@link #maxConcurrentSendsPerPartition(int) maxConcurrentSendsPerPartition} should not exceed 1. + * + *

+ * By default, this will be set to the number of processors available in the host environment. + *

+ * + * @param maxConcurrentSends The total number of batches that may be sent concurrently. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder maxConcurrentSends(int maxConcurrentSends) { + clientOptions.setMaxConcurrentSends(maxConcurrentSends); + return this; + } + + /** + * The number of batches that may be sent concurrently for a given partition. This option is superseded by + * the value specified for {@link #maxConcurrentSends(int) maxConcurrrentSends}, ensuring that limit is respected. + * + * @param maxConcurrentSendsPerPartition The number of batches that may be sent concurrently for a given partition. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder maxConcurrentSendsPerPartition(int maxConcurrentSendsPerPartition) { + clientOptions.setMaxConcurrentSendsPerPartition(maxConcurrentSendsPerPartition); + return this; + } + + /** + * The total number of events that can be buffered for publishing at a given time for a given partition. Once this + * capacity is reached, more events can enqueued by calling the {@code enqueueEvent} methods on either {@link + * EventHubBufferedProducerClient} or {@link EventHubBufferedProducerAsyncClient}. + * + * The default limit is 1500 queued events for each partition. + * + * @param maxEventBufferLengthPerPartition Total number of events that can be buffered for publishing at a given + * time. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder maxEventBufferLengthPerPartition(int maxEventBufferLengthPerPartition) { + clientOptions.setMaxPendingEventCount(maxEventBufferLengthPerPartition); + return this; + } + + /** + * The amount of time to wait for a batch to be built with events in the buffer before publishing a partially full + * batch. + * + * @param maxWaitTime The amount of time to wait. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder maxWaitTime(Duration maxWaitTime) { + clientOptions.setMaxWaitTime(maxWaitTime); + return this; + } + + /** + * The callback to invoke when publishing a set of events fails. + * + * @param sendFailedContext The callback to invoke. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder onSendBatchFailed( + Consumer sendFailedContext) { + clientOptions.setSendFailedContext(sendFailedContext); + return this; + } + + /** + * The callback to invoke when publishing a set of events succeeds. + * + * @param sendSucceededContext The callback to invoke when publishing a ste of events succeeds. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder onSendBatchSucceeded( + Consumer sendSucceededContext) { + clientOptions.setSendSucceededContext(sendSucceededContext); + return this; + } + + /** + * Sets the proxy configuration to use for the buffered producer. When a proxy is configured, {@link + * AmqpTransportType#AMQP_WEB_SOCKETS} must be used for the transport type. + * + * @param proxyOptions The proxy configuration to use. + * + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder proxyOptions(ProxyOptions proxyOptions) { + builder.proxyOptions(proxyOptions); + return this; + } + + /** + * Sets the retry policy for the producer client. If not specified, the default retry options are used. + * + * @param retryOptions The retry policy to use. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder retryOptions(AmqpRetryOptions retryOptions) { + builder.retryOptions(retryOptions); + return this; + } + + /** + * Sets the transport type by which all the communication with Azure Event Hubs occurs. Default value is {@link + * AmqpTransportType#AMQP}. + * + * @param transport The transport type to use. + * + * @return The updated {@link EventHubBufferedProducerClientBuilder} object. + */ + public EventHubBufferedProducerClientBuilder transportType(AmqpTransportType transport) { + builder.transportType(transport); + return this; + } + + + /** + * Builds a new instance of the async buffered producer client. + * + * @return A new instance of {@link EventHubBufferedProducerAsyncClient}. + */ + public EventHubBufferedProducerAsyncClient buildAsyncClient() { + return new EventHubBufferedProducerAsyncClient(builder, clientOptions); + } + + /** + * Builds a new instance of the buffered producer client. + * + * @return A new instance of {@link EventHubBufferedProducerClient}. + */ + public EventHubBufferedProducerClient buildClient() { + return null; + } +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/SendBatchFailedContext.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/SendBatchFailedContext.java new file mode 100644 index 000000000000..f8af315312ff --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/SendBatchFailedContext.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.messaging.eventhubs.models; + +import com.azure.messaging.eventhubs.EventData; +import com.azure.messaging.eventhubs.EventHubBufferedProducerAsyncClient; +import com.azure.messaging.eventhubs.EventHubBufferedProducerClient; + +/** + * Contains information about a batch that was unable to be published, as well as the exception that occurred and the + * partition that the batch was being published to. + * + * @see EventHubBufferedProducerClient + * @see EventHubBufferedProducerAsyncClient + */ +public final class SendBatchFailedContext { + private final Iterable events; + private final String partitionId; + private final Throwable throwable; + + /** + * Creates a new instance. + * + * @param events Events associated with the failed batch. + * @param partitionId Partition that the events went to. + * @param throwable Error associated with the failed batch. + */ + public SendBatchFailedContext(Iterable events, String partitionId, Throwable throwable) { + this.events = events; + this.partitionId = partitionId; + this.throwable = throwable; + } + + /** + * Gets the events that failed to send. + * + * @return The events that failed to send. + */ + public Iterable getEvents() { + return events; + } + + /** + * Gets the partition id that the failed batch went to. + * + * @return The partition id that the failed batch went to. + */ + public String getPartitionId() { + return partitionId; + } + + /** + * Gets the error that occurred when sending the batch. + * + * @return The error that occurred when sending the batch. + */ + public Throwable getThrowable() { + return throwable; + } +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/SendBatchSucceededContext.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/SendBatchSucceededContext.java new file mode 100644 index 000000000000..5a853d465cba --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/SendBatchSucceededContext.java @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.messaging.eventhubs.models; + +import com.azure.messaging.eventhubs.EventData; +import com.azure.messaging.eventhubs.EventHubBufferedProducerAsyncClient; +import com.azure.messaging.eventhubs.EventHubBufferedProducerClient; + +/** + * Contains information about a batch that was published and the partition that it was published to. + * + * @see EventHubBufferedProducerAsyncClient + * @see EventHubBufferedProducerClient + */ +public final class SendBatchSucceededContext { + private final String partitionId; + private final Iterable events; + + /** + * Initializes a new instance of the class. + * + * @param events The set of events in the batch that was published. + * @param partitionId The identifier of the partition that the batch was published to. + */ + public SendBatchSucceededContext(Iterable events, String partitionId) { + this.events = events; + this.partitionId = partitionId; + } + + /** + * Gets the set of events in the batch that was published. + * + * @return The set of events in the batch that was published. + */ + public Iterable getEvents() { + return events; + } + + /** + * Gets the identifier of the partition that the batch was published to. + * + * @return The identifier of the partition that the batch was published to. + */ + public String getPartitionId() { + return partitionId; + } +}