Skip to content

Commit 9c0ee48

Browse files
authored
chore(az.sb): provide new az msg handler interface w/o 'Azure...' (#653)
Provide a new interface alternative for message handlers without the `Azure...` noise. Relates to #548 discussion.
1 parent b8ad4dc commit 9c0ee48

File tree

20 files changed

+367
-109
lines changed

20 files changed

+367
-109
lines changed

docs/preview/02-getting-started.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,24 @@ First step in creating your message handler, is installing the following package
3131
PS> Install-Package -Name Arcus.Messaging.Pumps.ServiceBus
3232
```
3333

34-
The package makes the `IAzureServiceBusMessageHandler<>` interface available. Implementing this interface is the simplest way of creating a *'message handler'*.
34+
The package makes the `IServiceBusMessageHandler<>` interface available. Implementing this interface is the simplest way of creating a *'message handler'*.
3535

3636
As the generic type, you can use the DTO (data-transfer object) to which the [`ServiceBusReceivedMessage.Body`](https://learn.microsoft.com/en-us/dotnet/api/azure.messaging.servicebus.servicebusreceivedmessage.body) should be deserialized to (default via JSON). In this case: `MyOrder`.
3737

3838
```csharp
39-
using Arcus.Messaging.Abstractions.ServiceBus.MessagingHandling;
39+
using Arcus.Messaging.ServiceBus;
4040

4141
public class MyOrder
4242
{
4343
public string OrderId { get; set; }
4444
public string ProductName { get; set; }
4545
}
4646

47-
public class MyOrderMessageHandler : IAzureServiceBusMessageHandler<MyOrder>
47+
public class MyOrderMessageHandler : IServiceBusMessageHandler<MyOrder>
4848
{
4949
public async Task ProcessMessageAsync(
5050
MyOrder order,
51-
AzureServiceBusMessageContext context,
51+
ServiceBusMessageContext context,
5252
MessageCorrelationInfo correlation,
5353
CancellationToken cancellation)
5454
{

docs/preview/03-Features/01-Azure/01-service-bus.mdx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ To receive the Azure Service Bus message in a deserialized form, you can impleme
2323
Here is an example of such a message handler that expects messages of type `Order`:
2424

2525
```csharp
26-
using Arcus.Messaging.Abstractions.ServiceBus.MessagingHandling;
26+
using Arcus.Messaging.ServiceBus;
2727

2828
public class Order
2929
{
3030
public string OrderId { get; set; }
3131
public string ProductName { get; set; }
3232
}
3333

34-
public class OrderMessageHandler : IAzureServiceBusMessageHandler<Order>
34+
public class OrderMessageHandler : IServiceBusMessageHandler<Order>
3535
{
3636
private readonly ILogger _logger;
3737

@@ -44,7 +44,7 @@ public class OrderMessageHandler : IAzureServiceBusMessageHandler<Order>
4444
// Directly interact with your custom deserialized model (in this case 'Order'):
4545
public async Task ProcessMessageAsync(
4646
Order order,
47-
AzureServiceBusMessageContext context,
47+
ServiceBusMessageContext context,
4848
MessageCorrelationInfo correlation,
4949
CancellationToken cancellationToken)
5050
{
@@ -244,11 +244,13 @@ It is a good practice as application developer to dead-letter the message yourse
244244
:::
245245

246246
```csharp
247-
public class OrderMessageHandler : IAzureServiceBusMessageHandler<Order>
247+
using Arcus.Messaging.ServiceBus;
248+
249+
public class OrderMessageHandler : IServiceBusMessageHandler<Order>
248250
{
249251
public async Task Task ProcessMessageAsync(
250252
Order message,
251-
AzureServiceBusMessageContext messageContext,
253+
ServiceBusMessageContext messageContext,
252254
MessageCorrelationInfo correlation,
253255
CancellationToken cancellation)
254256
{
@@ -273,23 +275,20 @@ When your message handler interacts with an external dependency, that dependency
273275
To interact with the message processing system within your *message handler*, you can inherit from the `CircuitBreakerServiceBusMessageHandler<>`, which allows you to 'enrich' your handler with circuit-breaker functionality.
274276

275277
```csharp
276-
using Arcus.Messaging.Pumps.Abstractions.Resiliency;
278+
using Arcus.Messaging.ServiceBus;
277279

278280
// highlight-next-line
279-
public class OrderMessageHandler : CircuitBreakerServiceBusMessageHandler<Order>
281+
public class OrderMessageHandler : DefaultCircuitBreakerServiceBusMessageHandler<Order>
280282
{
281-
private readonly IMessagePumpCircuitBreaker _circuitBreaker;
282-
283283
public OrderMessageHandler(
284284
IMessagePumpCircuitBreaker circuitBreaker,
285285
ILogger<OrderMessageHandler> logger) : base(circuitBreaker, logger)
286286
{
287-
_circuitBreaker = circuitBreaker;
288287
}
289288

290289
public override async Task ProcessMessageAsync(
291290
Order message,
292-
AzureServiceBusMessageContext context,
291+
ServiceBusMessageContext context,
293292
MessageCorrelationInfo correlation,
294293
MessagePumpCircuitBreakerOptions options,
295294
CancellationToken cancellation)

docs/preview/03-Guides/migration-guide-v3.0.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ All Azure EventHubs-related functionality has been removed from v3.0. This means
5151
* `ServiceBusReceivedMessage.GetCorrelationInfo`
5252
* `ServiceBusReceivedMessage.GetApplicationProperty`
5353
* `MessageContext.GetMessageEncodingProperty`
54+
### ✏️ Renamed functionality
55+
* Renamed `IAzureServiceBusMessageHandler<>` to `IServiceBusMessageHandler<>` (in namespace `Arcus.Messaging.ServiceBus`)
56+
* Renamed `AzureServiceBusMessageContext` to `ServiceBusMessageContext` (in namespace `Arcus.Messaging.ServiceBus`)
57+
* Renamed `CircuitBreakerServiceBusMessageHandler<>` to `DefaultCircuitBreakerServiceBusMessageHandler<>` (in namespace `Arcus.Messaging.ServiceBus`)
5458

5559
### ✨ New Service Bus message pump registration
5660
Previously, the registration of the Azure Service Bus message pump involved navigating through the many available extensions, making it rather tedious to find the right authentication mechanism.
@@ -103,12 +107,14 @@ services.AddServiceBusQueueMessagePump(...)
103107
### ✨ New Service Bus message settlement
104108
Previous versions used dedicated 'template classes' that custom message handlers should inherit from to do custom Azure Service Bus message settlement (complete, dead-letter, abandon).
105109

106-
Starting from v3.0, the available operations are moved to the `AzureServiceBusMessageContext`. Making your custom message handlers much more accessible and flexible.
110+
Starting from v3.0, the available operations are moved to the `ServiceBusMessageContext` (previously called `AzureServiceBusMessageContext`). Making your custom message handlers much more accessible and flexible.
107111

108112
```diff
113+
+ using Arcus.Messaging.ServiceBus;
114+
109115
public class OrderServiceBusMessageHandler
110116
- : AzureServiceBusMessageHandler<Order>
111-
+ : IAzureServiceBusMessageHandler<Order>
117+
+ : IServiceBusMessageHandler<Order>
112118
{
113119
public OrderServiceBusMessageHandler(ILogger<OrderServiceBusMessageHandler> logger)
114120
- : base(logger)
@@ -119,7 +125,8 @@ public class OrderServiceBusMessageHandler
119125
- public override async Task ProcessMessageAsync(
120126
+ public async Task ProcessMessageAsync(
121127
Order order,
122-
AzureServiceBusMessageContext messageContext,
128+
- AzureServiceBusMessageContext messageContext,
129+
+ ServiceBusMessageContext messageContext,
123130
MessageCorrelationInfo messageCorrelation,
124131
CancellationToken cancellation)
125132
{

src/Arcus.Messaging.Abstractions.ServiceBus/AzureServiceBusMessageContext.cs

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,19 @@
33
using System.Linq;
44
using System.Threading;
55
using System.Threading.Tasks;
6+
using Arcus.Messaging.Abstractions;
7+
using Arcus.Messaging.Abstractions.ServiceBus;
8+
using Arcus.Messaging.ServiceBus;
69
using Azure.Messaging.ServiceBus;
710

8-
namespace Arcus.Messaging.Abstractions.ServiceBus
11+
namespace Arcus.Messaging.ServiceBus
912
{
10-
/// <summary>
11-
/// Represents the type of Azure Service Bus entity on which the message was received.
12-
/// </summary>
13-
public enum ServiceBusEntityType
14-
{
15-
/// <summary>
16-
/// The Azure Service Bus entity is a queue.
17-
/// </summary>
18-
Queue,
19-
20-
/// <summary>
21-
/// The Azure Service Bus entity is a topic subscription.
22-
/// </summary>
23-
Topic
24-
}
25-
2613
/// <summary>
2714
/// Represents the contextual information concerning an Azure Service Bus message.
2815
/// </summary>
29-
public class AzureServiceBusMessageContext : MessageContext
16+
public class ServiceBusMessageContext : MessageContext
3017
{
31-
private readonly IMessageSettleStrategy _messageSettle;
32-
33-
private AzureServiceBusMessageContext(
18+
internal ServiceBusMessageContext(
3419
string jobId,
3520
string fullyQualifiedNamespace,
3621
ServiceBusEntityType entityType,
@@ -39,7 +24,8 @@ private AzureServiceBusMessageContext(
3924
ServiceBusReceivedMessage message)
4025
: base(message.MessageId, jobId, message.ApplicationProperties.ToDictionary(item => item.Key, item => item.Value))
4126
{
42-
_messageSettle = messageSettle;
27+
MessageSettle = messageSettle;
28+
Message = message;
4329

4430
FullyQualifiedNamespace = fullyQualifiedNamespace;
4531
EntityPath = entityPath;
@@ -67,7 +53,7 @@ private AzureServiceBusMessageContext(
6753
public ServiceBusEntityType EntityType { get; }
6854

6955
/// <summary>
70-
/// Gets the contextual properties provided on the message provided by the Azure Service Bus runtime
56+
/// Gets the contextual properties provided on the message provided by the Azure Service Bus runtime.
7157
/// </summary>
7258
public AzureServiceBusSystemProperties SystemProperties { get; }
7359

@@ -83,14 +69,14 @@ private AzureServiceBusMessageContext(
8369
public int DeliveryCount { get; }
8470

8571
/// <summary>
86-
/// Creates a new instance of the <see cref="AzureServiceBusMessageContext"/> based on the current Azure Service bus situation.
72+
/// Creates a new instance of the <see cref="ServiceBusMessageContext"/> based on the current Azure Service bus situation.
8773
/// </summary>
8874
/// <param name="jobId">The unique ID to identity the Azure Service bus message pump that is responsible for pumping messages from the <paramref name="receiver"/>.</param>
8975
/// <param name="entityType">The type of Azure Service bus entity that the <paramref name="receiver"/> receives from.</param>
9076
/// <param name="receiver">The Azure Service bus receiver that is responsible for receiving the <paramref name="message"/>.</param>
9177
/// <param name="message">The Azure Service bus message that is currently being processed.</param>
9278
/// <exception cref="ArgumentNullException">Thrown when one of the parameters is <c>null</c>.</exception>
93-
public static AzureServiceBusMessageContext Create(
79+
public static ServiceBusMessageContext Create(
9480
string jobId,
9581
ServiceBusEntityType entityType,
9682
ServiceBusReceiver receiver,
@@ -101,7 +87,7 @@ public static AzureServiceBusMessageContext Create(
10187
ArgumentNullException.ThrowIfNull(message);
10288

10389
var messageSettle = new MessageSettleViaReceiver(receiver, message);
104-
return new AzureServiceBusMessageContext(jobId, receiver.FullyQualifiedNamespace, entityType, receiver.EntityPath, messageSettle, message);
90+
return new ServiceBusMessageContext(jobId, receiver.FullyQualifiedNamespace, entityType, receiver.EntityPath, messageSettle, message);
10591
}
10692

10793
/// <summary>
@@ -111,7 +97,7 @@ public static AzureServiceBusMessageContext Create(
11197
/// <param name="entityType">The type of Azure Service bus entity that the <paramref name="eventArgs"/> receives from.</param>
11298
/// <param name="eventArgs">The Azure Service bus event arguments upon receiving the message.</param>
11399
/// <exception cref="ArgumentNullException">Thrown when one of the parameters is <c>null</c>.</exception>
114-
public static AzureServiceBusMessageContext Create(
100+
public static ServiceBusMessageContext Create(
115101
string jobId,
116102
ServiceBusEntityType entityType,
117103
ProcessSessionMessageEventArgs eventArgs)
@@ -120,18 +106,20 @@ public static AzureServiceBusMessageContext Create(
120106
ArgumentNullException.ThrowIfNull(eventArgs);
121107

122108
var messageSettle = new MessageSettleViaSessionEventArgs(eventArgs);
123-
return new AzureServiceBusMessageContext(jobId, eventArgs.FullyQualifiedNamespace, entityType, eventArgs.EntityPath, messageSettle, eventArgs.Message);
109+
return new ServiceBusMessageContext(jobId, eventArgs.FullyQualifiedNamespace, entityType, eventArgs.EntityPath, messageSettle, eventArgs.Message);
124110
}
125111

126-
private interface IMessageSettleStrategy
112+
internal IMessageSettleStrategy MessageSettle { get; }
113+
internal ServiceBusReceivedMessage Message { get; }
114+
internal interface IMessageSettleStrategy
127115
{
128116
Task CompleteMessageAsync(CancellationToken cancellationToken);
129117
Task DeadLetterMessageAsync(string deadLetterReason, string deadLetterErrorDescription, CancellationToken cancellationToken);
130118
Task DeadLetterMessageAsync(string deadLetterReason, string deadLetterErrorDescription, IDictionary<string, object> newMessageProperties, CancellationToken cancellationToken);
131119
Task AbandonMessageAsync(IDictionary<string, object> newMessageProperties, CancellationToken cancellationToken);
132120
}
133121

134-
private sealed class MessageSettleViaReceiver : IMessageSettleStrategy
122+
internal sealed class MessageSettleViaReceiver : IMessageSettleStrategy
135123
{
136124
private readonly ServiceBusReceiver _receiver;
137125
private readonly ServiceBusReceivedMessage _message;
@@ -202,7 +190,7 @@ public Task AbandonMessageAsync(IDictionary<string, object> newMessageProperties
202190
/// <exception cref="InvalidOperationException">Thrown when the message handler was not initialized yet.</exception>
203191
public Task CompleteMessageAsync(CancellationToken cancellationToken)
204192
{
205-
return _messageSettle.CompleteMessageAsync(cancellationToken);
193+
return MessageSettle.CompleteMessageAsync(cancellationToken);
206194
}
207195

208196
/// <summary>
@@ -214,7 +202,7 @@ public Task CompleteMessageAsync(CancellationToken cancellationToken)
214202
/// <exception cref="InvalidOperationException">Thrown when the message handler was not initialized correctly.</exception>
215203
public Task DeadLetterMessageAsync(string deadLetterReason, string deadLetterErrorDescription, CancellationToken cancellationToken)
216204
{
217-
return _messageSettle.DeadLetterMessageAsync(deadLetterReason, deadLetterErrorDescription, cancellationToken);
205+
return MessageSettle.DeadLetterMessageAsync(deadLetterReason, deadLetterErrorDescription, cancellationToken);
218206
}
219207

220208
/// <summary>
@@ -227,7 +215,7 @@ public Task DeadLetterMessageAsync(string deadLetterReason, string deadLetterErr
227215
/// <exception cref="InvalidOperationException">Thrown when the message handler was not initialized yet.</exception>
228216
public Task DeadLetterMessageAsync(string deadLetterReason, string deadLetterErrorDescription, IDictionary<string, object> newMessageProperties, CancellationToken cancellationToken)
229217
{
230-
return _messageSettle.DeadLetterMessageAsync(deadLetterReason, deadLetterErrorDescription, newMessageProperties, cancellationToken);
218+
return MessageSettle.DeadLetterMessageAsync(deadLetterReason, deadLetterErrorDescription, newMessageProperties, cancellationToken);
231219
}
232220

233221
/// <summary>
@@ -243,7 +231,52 @@ public Task DeadLetterMessageAsync(string deadLetterReason, string deadLetterErr
243231
/// <exception cref="InvalidOperationException">Thrown when the message context was not initialized correctly.</exception>
244232
public Task AbandonMessageAsync(IDictionary<string, object> newMessageProperties, CancellationToken cancellationToken)
245233
{
246-
return _messageSettle.AbandonMessageAsync(newMessageProperties, cancellationToken);
234+
return MessageSettle.AbandonMessageAsync(newMessageProperties, cancellationToken);
235+
}
236+
}
237+
}
238+
239+
namespace Arcus.Messaging.Abstractions.ServiceBus
240+
{
241+
/// <summary>
242+
/// Represents the type of Azure Service Bus entity on which the message was received.
243+
/// </summary>
244+
public enum ServiceBusEntityType
245+
{
246+
/// <summary>
247+
/// The Azure Service Bus entity is a queue.
248+
/// </summary>
249+
Queue,
250+
251+
/// <summary>
252+
/// The Azure Service Bus entity is a topic subscription.
253+
/// </summary>
254+
Topic
255+
}
256+
257+
/// <summary>
258+
/// Represents the contextual information concerning an Azure Service Bus message.
259+
/// </summary>
260+
[Obsolete("Will be removed in v4.0, please use the " + nameof(ServiceBusMessageContext) + " instead")]
261+
public class AzureServiceBusMessageContext : ServiceBusMessageContext
262+
{
263+
internal AzureServiceBusMessageContext(
264+
string jobId,
265+
string fullyQualifiedNamespace,
266+
ServiceBusEntityType entityType,
267+
string entityPath,
268+
IMessageSettleStrategy messageSettle,
269+
ServiceBusReceivedMessage message)
270+
: base(jobId, fullyQualifiedNamespace, entityType, entityPath, messageSettle, message)
271+
{
272+
}
273+
274+
/// <summary>
275+
/// Initializes a deprecated <see cref="AzureServiceBusMessageContext"/> from the new <see cref="ServiceBusMessageContext"/>.
276+
/// </summary>
277+
public AzureServiceBusMessageContext(ServiceBusMessageContext context)
278+
: base(context.JobId, context.FullyQualifiedNamespace, context.EntityType, context.EntityPath, context.MessageSettle, context.Message)
279+
{
247280
}
248281
}
249282

0 commit comments

Comments
 (0)