Skip to content

Commit

Permalink
Additional samples (Azure#30430)
Browse files Browse the repository at this point in the history
* Additional samples

* fix

* Fix footer bug

* Fix check

* Fix links

* Make delivery annotations check consistent with other checks

* typos

* PR fb

* make tests
  • Loading branch information
JoshLove-msft authored and sofiar-msft committed Dec 7, 2022
1 parent b0f496f commit e0fffd7
Show file tree
Hide file tree
Showing 21 changed files with 445 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{8B8C
samples\Sample10_ClaimCheck.md = samples\Sample10_ClaimCheck.md
samples\Sample11_CloudEvents.md = samples\Sample11_CloudEvents.md
samples\Sample12_ManagingRules.md = samples\Sample12_ManagingRules.md
samples\Sample13_AdvancedConfiguration.md = samples\Sample13_AdvancedConfiguration.md
samples\Sample14_AMQPMessage.md = samples\Sample14_AMQPMessage.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Amqp", "..\..\core\Azure.Core.Amqp\src\Azure.Core.Amqp.csproj", "{2ADA26CA-77E5-4793-927A-A6185FD8AA29}"
Expand Down
18 changes: 0 additions & 18 deletions sdk/servicebus/Azure.Messaging.ServiceBus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ We guarantee that all client instance methods are thread-safe and independent of
* [Dead letter a message](#dead-letter-a-message)
* [Using the processor](#using-the-processor)
* [Authenticating with Azure.Identity](#authenticating-with-azureidentity)
* [Initiating the connection with a custom endpoint](#initiating-the-connection-with-a-custom-endpoint)
* [Working with sessions](#working-with-sessions)
* [More samples](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/README.md)

Expand Down Expand Up @@ -419,23 +418,6 @@ string fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";
ServiceBusClient client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());
```

### Initiating the connection with a custom endpoint

If an alternative host name is needed to establish the connection to the service, a custom endpoint address can be provided through the `ServiceBusClientOptions`. The client will use this endpoint to open the initial connection, and then will use the default endpoint provided by the Service Bus service for all following operations and validation.

```C# Snippet:ServiceBusCustomEndpoint
// Connect to the service using a custom endpoint
string connectionString = "<connection_string>";
string customEndpoint = "<custom_endpoint>";

var options = new ServiceBusClientOptions
{
CustomEndpointAddress = new Uri(customEndpoint)
};

ServiceBusClient client = new ServiceBusClient(connectionString, options);
```

### Working with Sessions

[Sessions](https://docs.microsoft.com/azure/service-bus-messaging/message-sessions) provide a mechanism for grouping related messages. In order to use sessions, you need to be working with a session-enabled entity.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sending and Receiving Messages

This sample demonstrates how to send and receive messages from a Service Bus queue.
This sample demonstrates how to send and receive messages from a Service Bus queue. Once a message is received, you will typically want to settle it. Message settlement is covered in detail in the [Settling Messages samples](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample02_MessageSettlement.md).

### Send and receive a message using queues

Expand Down Expand Up @@ -140,7 +140,7 @@ foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)

## Peeking a message

It's also possible to simply peek a message. Peeking a message does not require the message to be locked.
It's also possible to simply peek a message. Peeking a message does not require the message to be locked. Because the message is not locked to a specific receiver, the message will not be able to be settled. It's also possible that another receiver could lock the message and settle it while you are looking at the peeked message.

```C# Snippet:ServiceBusPeek
ServiceBusReceivedMessage peekedMessage = await receiver.PeekMessageAsync();
Expand All @@ -166,7 +166,7 @@ Cancelling the scheduled message will delete it from the service.
await sender.CancelScheduledMessageAsync(seq);
```

### Setting Time To Live
### Setting time to live

Message time to live can be configured at the queue or subscription level. By default, it is 14 days. Once this time has passed, the message is considered "expired". You can configure what happens to expired messages at the queue or subscription level. By default, these messages are deleted, but they can also be configured to move to the dead letter queue. More information about message expiry can be found [here](https://docs.microsoft.com/azure/service-bus-messaging/message-expiration). If you want to have an individual message expire before the entity-level configured time, you can set the `TimeToLive` property on the message.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync()
await receiver.CompleteMessageAsync(receivedMessage);
```

### Abandon a message
## Abandon a message

```C# Snippet:ServiceBusAbandonMessage
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
Expand All @@ -40,7 +40,7 @@ ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync()
await receiver.AbandonMessageAsync(receivedMessage);
```

### Defer a message
## Defer a message

```C# Snippet:ServiceBusDeferMessage
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
Expand All @@ -54,7 +54,7 @@ await receiver.DeferMessageAsync(receivedMessage);
ServiceBusReceivedMessage deferredMessage = await receiver.ReceiveDeferredMessageAsync(receivedMessage.SequenceNumber);
```

### Dead letter a message
## Dead letter a message

```C# Snippet:ServiceBusDeadLetterMessage
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
Expand All @@ -75,7 +75,7 @@ string reason = dlqMessage.DeadLetterReason;
string description = dlqMessage.DeadLetterErrorDescription;
```

### Renew the lock for a message and then complete it
## Renew the lock for a message and then complete it

```C# Snippet:ServiceBusRenewMessageLockAndComplete
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Sending and Receiving Session Messages
# Sending and Receiving Session Messages

This sample demonstrates how to send and receive session messages from a session-enabled Service Bus queue.

### Receiving from next available session
## Receiving from next available session

Receiving from sessions is performed using the `ServiceBusSessionReceiver`. This type derives from `ServiceBusReceiver` and exposes session-related functionality.

Expand Down Expand Up @@ -40,7 +40,7 @@ await receiver.SetSessionStateAsync(new BinaryData("some state"));
BinaryData state = await receiver.GetSessionStateAsync();
```

### Receive from a specific session
## Receive from a specific session

```C# Snippet:ServiceBusReceiveFromSpecificSession
// create a receiver specifying a particular session
Expand All @@ -51,7 +51,7 @@ ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync()
Console.WriteLine(receivedMessage.SessionId);
```

### Settling session messages
## Settling session messages

Settling session messages works in much the same way as settling non-session messages. The main difference is that the `ServiceBusSessionReceiver` type is used to settle the messages as opposed to the `ServiceBusReceiver` type. Additionally, session messages are not locked at the message level, but rather at the session level. Similar to how you can extend the message lock for an individual non-session messages, you can extend the session lock for a session which will prevent other consumers from receiving any messages from the session.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Using the Processor
# Using the Processor

This sample demonstrates how to use the processor. The processor offers automatic completion of processed messages, automatic message lock renewal, and concurrent execution of user specified event handlers.

### Processing messages
## Processing messages

```C# Snippet:ServiceBusProcessMessages
string connectionString = "<connection_string>";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Using the Session Processor
# Using the Session Processor

This sample demonstrates how to use the session processor. The session processor offers automatic completion of processed session messages, automatic session lock renewal, and concurrent execution of user specified event handlers.

### Processing messages from a session-enabled queue
## Processing messages from a session-enabled queue

Processing session messages is performed with a `ServiceBusSessionProcessor`. This type derives from `ServiceBusProcessor` and exposes session-related functionality.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Working with transactions
# Working with transactions

This sample demonstrates how to use [transactions](https://docs.microsoft.com/azure/service-bus-messaging/service-bus-transactions) with Service Bus. Transactions allow you to group operations together so that either all of them complete or none of them do. If any part of the transaction fails, the service will rollback the parts that succeeded on your behalf. You also can use familiar .NET semantics to complete or rollback the transaction using [TransactionScope](https://docs.microsoft.com/dotnet/api/system.transactions.transactionscope?view=netcore-3.1).

### Sending and completing a message in a transaction on the same entity
## Sending and completing a message in a transaction on the same entity

```C# Snippet:ServiceBusTransactionalSend
string connectionString = "<connection_string>";
Expand All @@ -22,7 +22,7 @@ using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
}
```

### Setting session state within a transaction
## Setting session state within a transaction

```C# Snippet:ServiceBusTransactionalSetSessionState
string connectionString = "<connection_string>";
Expand All @@ -44,7 +44,7 @@ using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
}
```

### Transactions across entities
## Transactions across entities

When creating senders and receivers that should be part of a cross-entity transaction, you can set the `EnableCrossEntityTransaction` property of the `ServiceBusClientOptions` as shown below. When using cross-entity transactions, the first entity that an operation occurs on becomes the entity through which all subsequent sends will be routed through. This enables the service to perform a transaction that is meant to span multiple entities. This means that subsequent entities that perform their first operation need to either be senders, or if they are receivers they need to be on the same entity as the initial entity through which all sends are routed through (otherwise the service would not be able to ensure that the transaction is committed because it cannot route a receive operation through a different entity). For instance, if you have SenderA and ReceiverB that are created from a client with cross-entity transactions enabled, you would need to receive first with ReceiverB to allow this to work. If you first used SenderA to send to QueueA, and then attempted to receive from QueueB, an `InvalidOperationException` would be thrown. You could still receive from a ReceiverA after initially sending to SenderA, since they are both using the same queue. This would be useful if you also had a SenderB that you want to include as part of the transaction (otherwise there would be no need to use cross-entity transactions as you would be dealing with only one entity).

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## CRUD operations
# CRUD operations

This sample demonstrates how to use the management client to manage entities within a namespace.

### Create a queue
## Create a queue

```C# Snippet:CreateQueue
string connectionString = "<connection_string>";
Expand Down Expand Up @@ -33,15 +33,15 @@ options.AuthorizationRules.Add(new SharedAccessAuthorizationRule(
QueueProperties createdQueue = await client.CreateQueueAsync(options);
```

### Get a queue
## Get a queue

You can retrieve an already created queue by supplying the queue name.

```C# Snippet:GetQueue
QueueProperties queue = await client.GetQueueAsync(queueName);
```

### Update a queue
## Update a queue

In order to update a queue, you will need to pass in the `QueueDescription` after getting it from `GetQueueAsync`.

Expand All @@ -50,15 +50,15 @@ queue.LockDuration = TimeSpan.FromSeconds(60);
QueueProperties updatedQueue = await client.UpdateQueueAsync(queue);
```

### Delete a queue
## Delete a queue

A queue can be deleted using the queue name.

```C# Snippet:DeleteQueue
await client.DeleteQueueAsync(queueName);
```

### Create a topic and subscription
## Create a topic and subscription

```C# Snippet:CreateTopicAndSubscription
string connectionString = "<connection_string>";
Expand Down Expand Up @@ -93,23 +93,23 @@ var subscriptionOptions = new CreateSubscriptionOptions(topicName, subscriptionN
SubscriptionProperties createdSubscription = await client.CreateSubscriptionAsync(subscriptionOptions);
```

### Get a topic
## Get a topic

You can retrieve an already created topic by supplying the topic name.

```C# Snippet:GetTopic
TopicProperties topic = await client.GetTopicAsync(topicName);
```

### Get a subscription
## Get a subscription

You can retrieve an already created subscription by supplying the topic and subscription names.

```C# Snippet:GetSubscription
SubscriptionProperties subscription = await client.GetSubscriptionAsync(topicName, subscriptionName);
```

### Update a topic
## Update a topic

In order to update a topic, you will need to pass in the `TopicDescription` after getting it from `GetTopicAsync`.

Expand All @@ -118,7 +118,7 @@ topic.UserMetadata = "some metadata";
TopicProperties updatedTopic = await client.UpdateTopicAsync(topic);
```

### Update a subscription
## Update a subscription

In order to update a subscription, you will need to pass in the `SubscriptionDescription` after getting it from `GetSubscriptionAsync`.

Expand All @@ -127,15 +127,15 @@ subscription.UserMetadata = "some metadata";
SubscriptionProperties updatedSubscription = await client.UpdateSubscriptionAsync(subscription);
```

### Delete a subscription
## Delete a subscription

A subscription can be deleted using the topic and subscription names.

```C# Snippet:DeleteSubscription
await client.DeleteSubscriptionAsync(topicName, subscriptionName);
```

### Delete a topic
## Delete a topic

A topic can be deleted using the topic name. Deleting a topic will automatically delete the associated subscriptions.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Interop with `WindowsAzure.ServiceBus`
# Interop with `WindowsAzure.ServiceBus`

This sample demonstrates how to interoperate with messages that are sent or received using the `WindowsAzure.ServiceBus` library. The `WindowsAzure.ServiceBus` library uses the `DataContractSerializer` to serialize the `BrokeredMessage` body. Because of this, when attempting to interoperate with this library, there a few additional steps that are needed.

### Sending a message using `Azure.Messaging.ServiceBus` that will be received with `WindowsAzure.ServiceBus`
## Sending a message using `Azure.Messaging.ServiceBus` that will be received with `WindowsAzure.ServiceBus`

```C# Snippet:ServiceBusInteropSend
ServiceBusSender sender = client.CreateSender(queueName);
Expand All @@ -26,7 +26,7 @@ var message = new ServiceBusMessage(stream.ToArray());
await sender.SendMessageAsync(message);
```

### Receiving a message using `Azure.Messaging.Service` that was sent with `WindowsAzure.ServiceBus`
## Receiving a message using `Azure.Messaging.Service` that was sent with `WindowsAzure.ServiceBus`

```C# Snippet:ServiceBusInteropReceive
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Extensibility
# Extensibility

This sample demonstrates how the key Service Bus types can be extended to provide custom functionality. As an example, we will demonstrate how messages can be intercepted and enriched before sending and after receiving. This mimics the functionality enabled by the `RegisterPlugin` method on client types in `Microsoft.Azure.ServiceBus`.

### Extending the types
## Extending the types

In our derived classes, we will allow consumers to specify code that should be run for incoming and outgoing messages.

Expand Down Expand Up @@ -124,7 +124,7 @@ public class PluginSessionProcessor : ServiceBusSessionProcessor
}
```

### Defining extension methods
## Defining extension methods
Since the `ServiceBusClient` manages the underlying connection for the senders, receivers, and processors, we will add extension methods to `ServiceBusClient` that will let us create the derived versions of the sender, receiver, and processor.
Here is how we define our extension methods so that these types can be created via the `ServiceBusClient`:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Claim check pattern
# Claim check pattern

This sample demonstrates the use of the [claim check pattern](https://docs.microsoft.com/azure/architecture/patterns/claim-check) which enables you to work with arbitrarily large message bodies. For standard namespaces, a message can be at most 256 KB. For Premium namespaces, the limit is 100 MB. If these limits don't work for your application you can leverage Azure Storage Blobs to implement this pattern.

### Sending the message
## Sending the message

In our example, we will assume that the message body can fit in memory. This allows us to use the Storage Blob methods that let you work with `BinaryData`. If your message body cannot fit in memory, you can use the [stream-based](https://docs.microsoft.com/dotnet/api/azure.storage.blobs.blobcontainerclient.uploadblobasync?view=azure-dotnet#Azure_Storage_Blobs_BlobContainerClient_UploadBlobAsync_System_String_System_IO_Stream_System_Threading_CancellationToken_) Upload/Download methods instead.

Expand Down Expand Up @@ -34,7 +34,7 @@ ServiceBusSender sender = client.CreateSender(scope.QueueName);
await sender.SendMessageAsync(message);
```

### Receiving the message
## Receiving the message

On the receiving side, we essentially perform the reverse of the operations that we did on the send side. We first receive our message and check for our application property key. After we find the key, we can download the corresponding blob.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Integrating with the CloudEvent type
# Integrating with the CloudEvent type

The Azure.Core library contains the [CloudEvent](https://docs.microsoft.com/dotnet/api/azure.messaging.cloudevent) type which conforms to the [CloudEvent JSON spec](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md). This type can be used in conjunction with the Service Bus library as shown below:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Managing Rules
# Managing Rules

As shown in the [CRUD operations sample](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample07_CrudOperations.md), rules can be created, deleted, and retrieved using the `ServiceBusAdministrationClient`. In order to perform these operations, you need to have `Manage` rights to the Service Bus namespace. When using Azure Identity, this translates to requiring the [Service Bus Data Owner role](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-service-bus-data-owner) be granted to your identity. It is also possible to perform these rule management operations using the `ServiceBusRuleManager` type. The major benefit to using this type is that you only need `Listen` rights for the subscription you wish to manage rules for, which corresponds to the [Service Bus Data Receiver role](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-service-bus-data-receiver). The following snippet provides an example of how to use this type.

Expand Down

0 comments on commit e0fffd7

Please sign in to comment.