diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Client/ServiceBusClient.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Client/ServiceBusClient.cs
index 1c51f4bbb274..c60f3bc5b34e 100644
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Client/ServiceBusClient.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Client/ServiceBusClient.cs
@@ -208,7 +208,9 @@ public ServiceBusSender CreateSender(string queueOrTopicName, string viaQueueOrT
///
/// Creates a instance that can be used for receiving and settling messages
- /// from a specific queue.
+ /// from a specific queue. It uses to specify how messages are received. Defaults to PeekLock mode.
+ /// If you want to change the , use method.
+ /// The is set in .
///
///
/// The queue to create a for.
@@ -226,7 +228,8 @@ public ServiceBusReceiver CreateReceiver(string queueName)
///
/// Creates a instance that can be used for receiving and settling messages
- /// from a specific queue.
+ /// from a specific queue. It uses to specify how messages are received. Defaults to PeekLock mode.
+ /// The is set in .
///
///
/// The queue to create a for.
@@ -249,7 +252,10 @@ public ServiceBusReceiver CreateReceiver(
///
/// Creates a instance that can be used for receiving and
- /// settling messages from a specific subscription.
+ /// settling messages from a specific subscription. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. If you want to change the ,
+ /// use method.
+ /// The is set in .
///
///
/// The topic to create a for.
@@ -272,7 +278,8 @@ public ServiceBusReceiver CreateReceiver(
///
/// Creates a instance that can be used for
- /// receiving and settling messages from a specific subscription.
+ /// receiving and settling messages from a specific subscription. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in .
///
///
/// The topic to create a for.
@@ -298,7 +305,8 @@ public ServiceBusReceiver CreateReceiver(
///
/// Creates a instance that can be used for receiving
- /// and settling messages from a specific session-enabled queue.
+ /// and settling messages from a specific session-enabled queue. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in .
///
///
/// The session-enabled queue to create a for.
@@ -332,7 +340,8 @@ public virtual async Task CreateSessionReceiverAsync(
///
/// Creates a instance that can be used for receiving
- /// and settling messages from a specific session-enabled subscription.
+ /// and settling messages from a specific session-enabled subscription. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in .
///
///
/// The topic to create a for.
@@ -368,7 +377,8 @@ public virtual async Task CreateSessionReceiverAsync(
///
/// Creates a instance that can be used for receiving from the
- /// dead letter queue for the specified queue.
+ /// dead letter queue for the specified queue. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in .
///
///
/// The queue to create a for.
@@ -392,7 +402,8 @@ public ServiceBusReceiver CreateDeadLetterReceiver(
///
/// Creates a instance that can be used for receiving from the
- /// dead letter queue for the specified subscription.
+ /// dead letter queue for the specified subscription. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in .
///
///
/// The topic to create a for.
@@ -421,7 +432,10 @@ public ServiceBusReceiver CreateDeadLetterReceiver(
///
/// Creates a instance that can be used to process messages using
- /// event handlers that are set on the processor.
+ /// event handlers that are set on the processor. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. If you want to change the ,
+ /// use method.
+ /// The is set in type.
///
///
/// The queue to create a for.
@@ -440,7 +454,8 @@ public ServiceBusProcessor CreateProcessor(string queueName)
///
/// Creates a instance that can be used to process messages using
- /// event handlers that are set on the processor.
+ /// event handlers that are set on the processor. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in type.
///
///
/// The queue to create a for.
@@ -463,7 +478,10 @@ public ServiceBusProcessor CreateProcessor(
///
/// Creates a instance that can be used to process messages using
- /// event handlers that are set on the processor.
+ /// event handlers that are set on the processor. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. If you want to change the ,
+ /// use method.
+ /// The is set in type.
///
///
/// The topic to create a for.
@@ -485,7 +503,8 @@ public ServiceBusProcessor CreateProcessor(
///
/// Creates a instance that can be used to process messages using
- /// event handlers that are set on the processor.
+ /// event handlers that are set on the processor. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in type.
///
///
/// The topic to create a for.
@@ -510,7 +529,8 @@ public ServiceBusProcessor CreateProcessor(
///
/// Creates a instance that can be used to process session messages using
- /// event handlers that are set on the processor.
+ /// event handlers that are set on the processor. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in type.
///
///
/// The queue to create a for.
@@ -535,7 +555,8 @@ public ServiceBusSessionProcessor CreateSessionProcessor(
///
/// Creates a instance that can be used to process
- /// messages using event handlers that are set on the processor.
+ /// messages using event handlers that are set on the processor. It uses to specify
+ /// how messages are received. Defaults to PeekLock mode. The is set in type.
///
///
/// The topic to create a for.
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Compatibility/ServiceBusClientBuilderExtensions.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Compatibility/ServiceBusClientBuilderExtensions.cs
index 3aaae0d2fdb8..7d987d158fb3 100644
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Compatibility/ServiceBusClientBuilderExtensions.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Compatibility/ServiceBusClientBuilderExtensions.cs
@@ -1,75 +1,44 @@
-#pragma warning disable SA1636 // File header copyright text should match
// Copyright (c) Microsoft Corporation. All rights reserved.
-#pragma warning restore SA1636 // File header copyright text should match
// Licensed under the MIT License.
-// ///
-// /// Registers a instance with the provided and
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubProducerClient(this TBuilder builder, string connectionString, string eventHubName)
-// where TBuilder : IAzureClientFactoryBuilder
-// {
-// return builder.RegisterClientFactory(options => new ServiceBusSenderClient(connectionString, eventHubName, options));
-// }
-// ///
-// /// Registers a instance with the provided and
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubProducerClientWithNamespace(this TBuilder builder, string fullyQualifiedNamespace, string eventHubName)
-// where TBuilder : IAzureClientFactoryBuilderWithCredential
-// {
-// return builder.RegisterClientFactory((options, token) => new ServiceBusSenderClient(fullyQualifiedNamespace, eventHubName, token, options));
-// }
+using Azure.Core.Extensions;
+using Azure.Messaging.ServiceBus;
-// ///
-// /// Registers a instance with connection options loaded from the provided instance.
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubProducerClient(this TBuilder builder, TConfiguration configuration)
-// where TBuilder : IAzureClientFactoryBuilderWithConfiguration
-// {
-// return builder.RegisterClientFactory(configuration);
-// }
+namespace Microsoft.Extensions.Azure
+{
+ ///
+ /// The set of extensions to add the Service Bus client types to the clients builder
+ ///
+ public static class ServiceBusClientBuilderExtensions
+ {
+ ///
+ /// Registers a instance with the provided .
+ ///
+ ///
+ public static IAzureClientBuilder AddServiceBusClient(this TBuilder builder, string connectionString)
+ where TBuilder : IAzureClientFactoryBuilder
+ {
+ return builder.RegisterClientFactory(options => new ServiceBusClient(connectionString, options));
+ }
-// ///
-// /// Registers a instance with the provided
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubConsumerClient(this TBuilder builder, string consumerGroup, string connectionString)
-// where TBuilder : IAzureClientFactoryBuilder
-// {
-// return builder.RegisterClientFactory(options => new ServiceBusReceiverClient(consumerGroup, connectionString, options));
-// }
+ ///
+ /// Registers a instance with the provided .
+ ///
+ ///
+ public static IAzureClientBuilder AddServiceBusClientWithNamespace(this TBuilder builder, string fullyQualifiedNamespace)
+ where TBuilder : IAzureClientFactoryBuilderWithCredential
+ {
+ return builder.RegisterClientFactory((options, token) => new ServiceBusClient(fullyQualifiedNamespace, token, options));
+ }
-// ///
-// /// Registers a instance with the provided and
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubConsumerClient(this TBuilder builder, string consumerGroup, string connectionString, string eventHubName)
-// where TBuilder : IAzureClientFactoryBuilder
-// {
-// return builder.RegisterClientFactory(options => new ServiceBusReceiverClient(connectionString, eventHubName, options));
-// }
-
-// ///
-// /// Registers a instance with the provided and
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubConsumerClientWithNamespace(this TBuilder builder, string consumerGroup, string fullyQualifiedNamespace, string eventHubName)
-// where TBuilder : IAzureClientFactoryBuilderWithCredential
-// {
-// return builder.RegisterClientFactory((options, token) => new ServiceBusReceiverClient(fullyQualifiedNamespace, eventHubName, token, options));
-// }
-
-// ///
-// /// Registers a instance with connection options loaded from the provided instance.
-// ///
-// ///
-// public static IAzureClientBuilder AddEventHubConsumerClient(this TBuilder builder, TConfiguration configuration)
-// where TBuilder : IAzureClientFactoryBuilderWithConfiguration
-// {
-// return builder.RegisterClientFactory(configuration);
-// }
-// }
-//}
+ ///
+ /// Registers a instance with connection options loaded from the provided instance.
+ ///
+ ///
+ public static IAzureClientBuilder AddServiceBusClient(this TBuilder builder, TConfiguration configuration)
+ where TBuilder : IAzureClientFactoryBuilderWithConfiguration
+ {
+ return builder.RegisterClientFactory(configuration);
+ }
+ }
+}
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusProcessor.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusProcessor.cs
index 124caa1d2bd6..6b89ed61ed21 100644
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusProcessor.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusProcessor.cs
@@ -15,9 +15,9 @@
namespace Azure.Messaging.ServiceBus
{
///
- /// A is responsible for processing from a specific
- /// entity using event handlers. It is constructed by calling
- /// .
+ /// The provides an abstraction around a set of that
+ /// allows using an event based model for processing received . It is constructed by calling
+ /// .
/// The event handler is specified with the
/// property. The error handler is specified with the property.
/// To start processing after the handlers have been specified, call .
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusSessionProcessor.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusSessionProcessor.cs
index 1a9c73c77a30..5f518a028f85 100644
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusSessionProcessor.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Processor/ServiceBusSessionProcessor.cs
@@ -10,10 +10,9 @@
namespace Azure.Messaging.ServiceBus
{
///
- /// A is responsible for processing
- /// from a specific entity using event handlers.
- /// It is constructed by calling
- /// .
+ /// The provides an abstraction around a set of that
+ /// allows using an event based model for processing received .
+ /// It is constructed by calling .
/// The event handler is specified with the
/// property. The error handler is specified with the property.
/// To start processing after the handlers have been specified, call .
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Receiver/ServiceBusReceiver.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Receiver/ServiceBusReceiver.cs
index f2ec40c5d097..b56bfba1a765 100644
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Receiver/ServiceBusReceiver.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Receiver/ServiceBusReceiver.cs
@@ -132,7 +132,7 @@ internal ServiceBusReceiver(
protected ServiceBusReceiver() { }
///
- /// Receives a batch of from the entity using mode.
+ /// Receives a batch of from the entity using mode. defaults to PeekLock mode.
///
///
/// The maximum number of messages that will be received.
@@ -171,7 +171,7 @@ public virtual async Task> ReceiveBatchAsync(
}
///
- /// Receives a from the entity using mode.
+ /// Receives a from the entity using mode. defaults to PeekLock mode
///
/// An optional specifying the maximum time to wait for a message before returning a null if no messages are available.
/// If not specified, the will be used.
@@ -369,8 +369,11 @@ public virtual async Task CompleteAsync(
/// A task to be resolved on when the operation has completed.
public virtual async Task CompleteAsync(
string lockToken,
- CancellationToken cancellationToken = default) =>
+ CancellationToken cancellationToken = default)
+ {
+ ThrowIfLockTokenIsEmpty(lockToken);
await CompleteAsync(new[] { lockToken }, cancellationToken).ConfigureAwait(false);
+ }
///
/// Completes a series of . This will delete the message from the service.
@@ -482,7 +485,7 @@ public virtual async Task AbandonAsync(
IDictionary propertiesToModify = null,
CancellationToken cancellationToken = default)
{
- Argument.AssertNotNull(lockToken, nameof(lockToken));
+ ThrowIfLockTokenIsEmpty(lockToken);
Argument.AssertNotClosed(IsDisposed, nameof(ServiceBusReceiver));
ThrowIfNotPeekLockMode();
cancellationToken.ThrowIfCancellationRequested();
@@ -637,7 +640,7 @@ private async Task DeadLetterInternalAsync(
IDictionary propertiesToModify = default,
CancellationToken cancellationToken = default)
{
- Argument.AssertNotNull(lockToken, nameof(lockToken));
+ ThrowIfLockTokenIsEmpty(lockToken);
Argument.AssertNotClosed(IsDisposed, nameof(ServiceBusReceiver));
cancellationToken.ThrowIfCancellationRequested();
ThrowIfNotPeekLockMode();
@@ -711,7 +714,7 @@ public virtual async Task DeferAsync(
IDictionary propertiesToModify = null,
CancellationToken cancellationToken = default)
{
- Argument.AssertNotNull(lockToken, nameof(lockToken));
+ ThrowIfLockTokenIsEmpty(lockToken);
Argument.AssertNotClosed(IsDisposed, nameof(ServiceBusReceiver));
ThrowIfNotPeekLockMode();
cancellationToken.ThrowIfCancellationRequested();
@@ -745,6 +748,17 @@ private void ThrowIfNotPeekLockMode()
}
}
+ ///
+ /// Throws an InvalidOperationException when the lock token is empty.
+ ///
+ private void ThrowIfLockTokenIsEmpty(string lockToken)
+ {
+ if (Guid.Parse(lockToken) == Guid.Empty)
+ {
+ throw new InvalidOperationException(Resources.SettlementOperationNotSupported);
+ }
+ }
+
///
/// Receives a specific deferred message identified by .
///
@@ -848,7 +862,7 @@ public virtual async Task RenewMessageLockAsync(
string lockToken,
CancellationToken cancellationToken = default)
{
- Argument.AssertNotNull(lockToken, nameof(lockToken));
+ ThrowIfLockTokenIsEmpty(lockToken);
Argument.AssertNotClosed(IsDisposed, nameof(ServiceBusReceiver));
ThrowIfNotPeekLockMode();
ThrowIfSessionReceiver();
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.Designer.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.Designer.cs
index 844ec296760a..448832491811 100755
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.Designer.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.Designer.cs
@@ -492,6 +492,15 @@ internal static string SessionLockExpiredOnMessageSession {
}
}
+ ///
+ /// Looks up a localized string similar to The operation is not supported for peeked message. Only received message can be settled..
+ ///
+ internal static string SettlementOperationNotSupported {
+ get {
+ return ResourceManager.GetString("SettlementOperationNotSupported", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to In order to update the signature, a shared access key must have been provided when the shared access signature was created..
///
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.resx b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.resx
index 1aede7c6603c..9a01a717fe62 100755
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.resx
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.resx
@@ -297,4 +297,7 @@
The message batch is currently being used in communication with the Service Bus service; messages may not be added until the active operation is complete.
+
+ The operation is not supported for peeked message. Only received message can be settled.
+
\ No newline at end of file
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Sender/ServiceBusSender.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Sender/ServiceBusSender.cs
index 14a8df197a67..541dfeef697b 100755
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Sender/ServiceBusSender.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Sender/ServiceBusSender.cs
@@ -9,7 +9,6 @@
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
-using Azure.Core.Pipeline;
using Azure.Messaging.ServiceBus.Core;
using Azure.Messaging.ServiceBus.Diagnostics;
@@ -17,7 +16,7 @@ namespace Azure.Messaging.ServiceBus
{
///
/// A client responsible for sending to a specific Service Bus entity
- /// (Queue or Topic). It is constructed by calling .
+ /// (Queue or Topic). It can be used for both session and non-session entities. It is constructed by calling .
///
///
public class ServiceBusSender : IAsyncDisposable
diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/ReceiverLiveTests.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/ReceiverLiveTests.cs
index 45701650703d..0a08bb983809 100644
--- a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/ReceiverLiveTests.cs
+++ b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/ReceiverLiveTests.cs
@@ -413,5 +413,105 @@ public async Task MaxWaitTimeRespected()
Assert.IsTrue(diff.TotalSeconds > 10);
}
}
+
+ [Test]
+ public async Task ThrowIfCompletePeekedMessage()
+ {
+ await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
+ {
+ await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
+
+ ServiceBusSender sender = client.CreateSender(scope.QueueName);
+ await sender.SendAsync(GetMessage());
+
+ var receiver = client.CreateReceiver(scope.QueueName);
+
+ var peekedMessage = await receiver.PeekAsync();
+
+ Assert.That(
+ async () => await receiver.CompleteAsync(peekedMessage),
+ Throws.InstanceOf());
+ }
+ }
+
+ [Test]
+ public async Task ThrowIfAbandonPeekedMessage()
+ {
+ await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
+ {
+ await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
+
+ ServiceBusSender sender = client.CreateSender(scope.QueueName);
+ await sender.SendAsync(GetMessage());
+
+ var receiver = client.CreateReceiver(scope.QueueName);
+
+ var peekedMessage = await receiver.PeekAsync();
+
+ Assert.That(
+ async () => await receiver.AbandonAsync(peekedMessage),
+ Throws.InstanceOf());
+ }
+ }
+
+ [Test]
+ public async Task ThrowIfDeferPeekedMessage()
+ {
+ await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
+ {
+ await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
+
+ ServiceBusSender sender = client.CreateSender(scope.QueueName);
+ await sender.SendAsync(GetMessage());
+
+ var receiver = client.CreateReceiver(scope.QueueName);
+
+ var peekedMessage = await receiver.PeekAsync();
+
+ Assert.That(
+ async () => await receiver.DeferAsync(peekedMessage),
+ Throws.InstanceOf());
+ }
+ }
+
+ [Test]
+ public async Task ThrowIfDeadletterPeekedMessage()
+ {
+ await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
+ {
+ await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
+
+ ServiceBusSender sender = client.CreateSender(scope.QueueName);
+ await sender.SendAsync(GetMessage());
+
+ var receiver = client.CreateReceiver(scope.QueueName);
+
+ var peekedMessage = await receiver.PeekAsync();
+
+ Assert.That(
+ async () => await receiver.DeadLetterAsync(peekedMessage),
+ Throws.InstanceOf());
+ }
+ }
+
+ [Test]
+ public async Task ThrowIfRenewlockOfPeekedMessage()
+ {
+ await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
+ {
+ await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
+
+ ServiceBusSender sender = client.CreateSender(scope.QueueName);
+ await sender.SendAsync(GetMessage());
+
+ var receiver = client.CreateReceiver(scope.QueueName);
+
+ var peekedMessage = await receiver.PeekAsync();
+
+ Assert.That(
+ async () => await receiver.RenewMessageLockAsync(peekedMessage),
+ Throws.InstanceOf());
+ }
+ }
}
}