Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
CHANGELOG.md = CHANGELOG.md
CONTRIBUTING.md = CONTRIBUTING.md
MigrationGuide.md = MigrationGuide.md
README.md = README.md
EndProjectSection
EndProject
Expand Down
6 changes: 3 additions & 3 deletions sdk/servicebus/Azure.Messaging.ServiceBus/MigrationGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ The v4 client allowed for sending a single message or a list of messages, which
| In v4 | Equivalent in v7 | Sample |
|------------------------------------------------|------------------------------------------------------------------|--------|
| `QueueClient.SendAsync(Message)` or `MessageSender.SendAsync(Message)` | `ServiceBusSender.SendAsync(ServiceBusMessage)` | [Send a message](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample01_HelloWorld.md#sending-and-receiving-a-message) |
| `QueueClient.SendAsync(IList<Message>)` or `MessageSender.SendAsync(IList<Message>)` | `messageBatch = ServiceBusSender.CreateBatchAsync()` `messageBatch.TryAdd(ServiceBusMessage)` `ServiceBusSender.SendBatchAsync(messageBatch)` | [Send a batch of messages](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample01_HelloWorld.md#sending-and-receiving-a-batch-of-messages) |
| `QueueClient.SendAsync(IList<Message>)` or `MessageSender.SendAsync(IList<Message>)` | `messageBatch = ServiceBusSender.CreateBatchAsync()` `messageBatch.TryAdd(ServiceBusMessage)` `ServiceBusSender.SendAsync(messageBatch)` | [Send a batch of messages](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample01_HelloWorld.md#sending-and-receiving-a-batch-of-messages) |

### Receiving messages

Expand Down Expand Up @@ -157,7 +157,7 @@ Console.WriteLine(body);

In v4, `QueueClient`/`MessageSender`/`MessageReceiver` would be created directly, after which user would call `SendAsync()` method via `QueueClient`/`MessageSender` to send a batch of messages and `ReceiveAsync()` method via `MessageReceiver` to receive a batch of messages.

In v7, user would initialize the `ServiceBusClient` and call `CreateSender()` method to create a `ServiceBusSender` and `CreateReceiver()` method to create a `ServiceBusReceiver`. To send a batch of messages, user would call `CreateBatchAsync()` method to create `ServiceBusMessageBatch` and try to add messages to it using `TryAdd()` method. If the `ServiceBusMessageBatch` accepts a message, user can be confident that it will not violate size constraints when calling `SendBatchAsync()` via `ServiceBusSender`. To receive a batch of messages, user would call `ReceiveBatchAsync()` method via `ServiceBusReceiver`.
In v7, user would initialize the `ServiceBusClient` and call `CreateSender()` method to create a `ServiceBusSender` and `CreateReceiver()` method to create a `ServiceBusReceiver`. To send a batch of messages, user would call `CreateBatchAsync()` method to create `ServiceBusMessageBatch` and try to add messages to it using `TryAdd()` method. If the `ServiceBusMessageBatch` accepts a message, user can be confident that it will not violate size constraints when calling `SendAsync()` via `ServiceBusSender`. To receive a batch of messages, user would call `ReceiveBatchAsync()` method via `ServiceBusReceiver`.

In v4:

Expand Down Expand Up @@ -216,7 +216,7 @@ messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);
Copy link
Copy Markdown
Member

@ShivangiReja ShivangiReja Apr 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we update SendBatchAsync -> SendAsync in the Sending messages section and in the description of Sending and receiving batch of messages?


// create a receiver that we can use to receive the messages
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
Expand Down
4 changes: 2 additions & 2 deletions sdk/servicebus/Azure.Messaging.ServiceBus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);

// create a receiver that we can use to receive the messages
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
Expand Down Expand Up @@ -233,7 +233,7 @@ messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);

// get the options to use for configuring the processor
var options = new ServiceBusProcessorOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);

// create a receiver that we can use to receive the messages
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);

// get the options to use for configuring the processor
var options = new ServiceBusProcessorOptions
Expand Down Expand Up @@ -100,7 +100,7 @@ messageBatch.TryAdd(
});

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);

// get the options to use for configuring the processor
var options = new ServiceBusProcessorOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ messageBatch.TryAdd(
});

// send the message batch
await sender.SendBatchAsync(messageBatch);
await sender.SendAsync(messageBatch);

// get the options to use for configuring the processor
var options = new ServiceBusProcessorOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,34 +175,27 @@ public ServiceBusSender CreateSender(string queueOrTopicName)

return new ServiceBusSender(
entityPath: queueOrTopicName,
viaEntityPath: null,
options: new ServiceBusSenderOptions(),
connection: Connection);
}

/// <summary>
/// Creates a <see cref="ServiceBusSender"/> instance that can be used for sending messages to a specific
/// queue or topic via a different queue or topic.
/// queue or topic.
/// </summary>
///
/// <param name="queueOrTopicName">The queue or topic to create a <see cref="ServiceBusSender"/> for.</param>
/// <param name="viaQueueOrTopicName"></param>
///
/// <remarks>
/// This is mainly to be used when sending messages in a transaction.
/// When messages need to be sent across entities in a single transaction, this can be used to ensure
/// all the messages land initially in the same entity/partition for local transactions, and then
/// let Service Bus handle transferring the message to the actual destination.
/// </remarks>
/// <param name="options">The set of <see cref="ServiceBusSenderOptions"/> to use for configuring
/// this <see cref="ServiceBusSender"/>.</param>
///
/// <returns>A <see cref="ServiceBusSender"/> scoped to the specified queue or topic.</returns>
public ServiceBusSender CreateSender(string queueOrTopicName, string viaQueueOrTopicName)
public ServiceBusSender CreateSender(string queueOrTopicName, ServiceBusSenderOptions options)
{
ValidateEntityName(viaQueueOrTopicName);
ValidateEntityName(queueOrTopicName);
ValidateSendViaEntityName(queueOrTopicName, options?.ViaQueueOrTopicName);

return new ServiceBusSender(
entityPath: queueOrTopicName,
viaEntityPath: viaQueueOrTopicName,
options: options,
connection: Connection);
}

Expand Down Expand Up @@ -616,5 +609,30 @@ private void ValidateEntityName(string entityName)
throw new ArgumentException(Resources.OnlyOneEntityNameMayBeSpecified);
}
}

/// <summary>
/// Validates that the specified entity name matches the entity path in the Connection,
/// if an entity path is specified in the connection.
/// </summary>
/// <param name="entityName">Entity name to validate</param>
///
/// <param name="sendViaEntityName">The send via entity name to validate</param>
private void ValidateSendViaEntityName(string entityName, string sendViaEntityName)
{
if (sendViaEntityName == null ||
string.Equals(sendViaEntityName, entityName, StringComparison.InvariantCultureIgnoreCase))
{
ValidateEntityName(sendViaEntityName);
return;
}

// we've established they are not equal, so anything specified in connection string will cause
// a mismatch with one of the entities.

if (!string.IsNullOrEmpty(Connection.EntityPath))
{
throw new ArgumentException(Resources.SendViaCannotBeUsedWithEntityInConnectionString);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions sdk/servicebus/Azure.Messaging.ServiceBus/src/Resources.resx
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,7 @@
<data name="SettlementOperationNotSupported" xml:space="preserve">
<value>The operation is not supported for peeked message. Only received message can be settled.</value>
</data>
<data name="SendViaCannotBeUsedWithEntityInConnectionString" xml:space="preserve">
<value>When sending via a different entity, an entity path is not allowed to specified in the connection string.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
namespace Azure.Messaging.ServiceBus
{
/// <summary>
/// A set of <see cref="ServiceBusMessageBatch" /> with size constraints known up-front,
/// A set of <see cref="ServiceBusMessage" /> with size constraints known up-front,
/// intended to be sent to the Queue/Topic as a single batch.
/// A <see cref="ServiceBusMessageBatch"/> can be created using
/// <see cref="ServiceBusSender.CreateBatchAsync(System.Threading.CancellationToken)"/>.
/// Messages can be added to the batch using the <see cref="TryAdd"/> method on the batch.
Comment on lines 12 to 16
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add this Messages can be added to the batch using the <see cref="TryAdd"/> method on the batch for CreateBatchAsync docs as well?

/// </summary>
///
public sealed class ServiceBusMessageBatch : IDisposable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,29 @@ public class ServiceBusSender : IAsyncDisposable
/// Initializes a new instance of the <see cref="ServiceBusSender"/> class.
/// </summary>
/// <param name="entityPath">The entity path to send the message to.</param>
/// <param name="viaEntityPath">The entity path to route the message through. Useful when using transactions.</param>
/// <param name="options">The set of <see cref="ServiceBusSenderOptions"/> to use for configuring
/// this <see cref="ServiceBusSender"/>.</param>
/// <param name="connection">The connection for the sender.</param>
///
internal ServiceBusSender(
string entityPath,
string viaEntityPath,
ServiceBusSenderOptions options,
ServiceBusConnection connection)
{
Argument.AssertNotNull(connection, nameof(connection));
Argument.AssertNotNull(connection.RetryOptions, nameof(connection.RetryOptions));
Argument.AssertNotNullOrWhiteSpace(entityPath, nameof(entityPath));
connection.ThrowIfClosed();

options = options?.Clone() ?? new ServiceBusSenderOptions();
EntityPath = entityPath;
ViaEntityPath = viaEntityPath;
ViaEntityPath = options.ViaQueueOrTopicName;
Identifier = DiagnosticUtilities.GenerateIdentifier(EntityPath);
_connection = connection;
_retryPolicy = _connection.RetryOptions.ToRetryPolicy();
_innerSender = _connection.CreateTransportSender(
entityPath,
viaEntityPath,
ViaEntityPath,
_retryPolicy);
}

Expand Down Expand Up @@ -138,7 +140,7 @@ await SendAsync(
/// Sends a set of messages to the associated Service Bus entity using a batched approach.
/// If the size of the messages exceed the maximum size of a single batch,
/// an exception will be triggered and the send will fail. In order to ensure that the messages
/// being sent will fit in a batch, use <see cref="SendBatchAsync"/> instead.
/// being sent will fit in a batch, use <see cref="SendAsync(ServiceBusMessageBatch, CancellationToken)"/> instead.
/// </summary>
///
/// <param name="messages">The set of messages to send.</param>
Expand Down Expand Up @@ -176,12 +178,13 @@ await _innerSender.SendAsync(
}

/// <summary>
/// Creates a size-constraint batch to which <see cref="ServiceBusMessage" /> may be added using a try-based pattern. If a message would
/// exceed the maximum allowable size of the batch, the batch will not allow adding the message and signal that scenario using its
/// return value.
/// Creates a size-constraint batch to which <see cref="ServiceBusMessage" /> may be added using
/// a <see cref="ServiceBusMessageBatch.TryAdd"/>. If a message would exceed the maximum
/// allowable size of the batch, the batch will not allow adding the message and signal that
/// scenario using it return value.
///
/// Because messages that would violate the size constraint cannot be added, publishing a batch will not trigger an exception when
/// attempting to send the messages to the Queue/Topic.
/// Because messages that would violate the size constraint cannot be added, publishing a batch
/// will not trigger an exception when attempting to send the messages to the Queue/Topic.
/// </summary>
///
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
Expand Down Expand Up @@ -233,15 +236,16 @@ public virtual async ValueTask<ServiceBusMessageBatch> CreateBatchAsync(
}

/// <summary>
/// Sends a set of messages to the associated Service Bus entity using a batched approach. If the size of messages exceed the
/// maximum size of a single batch, an exception will be triggered and the send will fail.
/// Sends a <see cref="ServiceBusMessageBatch"/>
/// containing a set of <see cref="ServiceBusMessage"/> to
/// the associated Service Bus entity.
/// </summary>
///
/// <param name="messageBatch">The set of messages to send. A batch may be created using <see cref="CreateBatchAsync(CancellationToken)" />.</param>
/// <param name="messageBatch">The batch of messages to send. A batch may be created using <see cref="CreateBatchAsync(CancellationToken)" />.</param>
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
/// <returns>A task to be resolved on when the operation has completed.</returns>
///
public virtual async Task SendBatchAsync(
public virtual async Task SendAsync(
ServiceBusMessageBatch messageBatch,
CancellationToken cancellationToken = default)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.ComponentModel;

namespace Azure.Messaging.ServiceBus
{
/// <summary>
/// The set of options that can be specified when creating a <see cref="ServiceBusSender"/>
/// to configure its behavior.
/// </summary>
public class ServiceBusSenderOptions
{
/// <summary>
/// The queue or topic name to route the message through. This is useful when using transactions, in order
/// to allow for completing a transaction involving multiple entities. For instance, if you want to
/// settle a message on Entity A and send a message to Entity B as part of the same transaction,
/// you can use a <see cref="ServiceBusSender"/> for Entity B, with the <see cref="ViaQueueOrTopicName"/>
/// property set to Entity A.
/// </summary>
public string ViaQueueOrTopicName { get; set; }

/// <summary>
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
/// </summary>
///
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
///
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj) => base.Equals(obj);

/// <summary>
/// Returns a hash code for this instance.
/// </summary>
///
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode();

/// <summary>
/// Converts the instance to string representation.
/// </summary>
///
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();

/// <summary>
/// Creates a new copy of the current <see cref="ServiceBusSenderOptions" />, cloning its attributes into a new instance.
/// </summary>
///
/// <returns>A new copy of <see cref="ServiceBusSenderOptions" />.</returns>
internal ServiceBusSenderOptions Clone() =>
new ServiceBusSenderOptions
{
ViaQueueOrTopicName = ViaQueueOrTopicName
};
}
}
Loading