@@ -44,7 +44,6 @@ public async Task Dispatch(TransportOperations outgoingMessages, TransportTransa
44
44
Dictionary < string , List < IOutgoingTransportOperation > > ? defaultOperationsPerDestination = null ;
45
45
var numberOfDefaultOperations = 0 ;
46
46
var numberOfIsolatedOperations = 0 ;
47
- var numberOfDefaultOperationDestinations = 0 ;
48
47
49
48
foreach ( var operation in transportOperations )
50
49
{
@@ -59,8 +58,6 @@ public async Task Dispatch(TransportOperations outgoingMessages, TransportTransa
59
58
if ( ! defaultOperationsPerDestination . ContainsKey ( destination ) )
60
59
{
61
60
defaultOperationsPerDestination [ destination ] = [ operation ] ;
62
- // because we batch only the number of destinations are relevant
63
- numberOfDefaultOperationDestinations ++ ;
64
61
}
65
62
else
66
63
{
@@ -91,14 +88,15 @@ public async Task Dispatch(TransportOperations outgoingMessages, TransportTransa
91
88
throw new Exception ( $ "The number of outgoing messages ({ numberOfDefaultOperations } ) exceeds the limits permitted by Azure Service Bus ({ MaxMessageThresholdForTransaction } ) in a single transaction") ;
92
89
}
93
90
94
- var concurrentDispatchTasks =
95
- new List < Task > ( numberOfIsolatedOperations + numberOfDefaultOperationDestinations ) ;
96
- AddIsolatedOperationsTo ( concurrentDispatchTasks , isolatedOperationsPerDestination ?? emptyDestinationAndOperations , transaction , azureServiceBusTransaction , cancellationToken ) ;
97
- AddBatchedOperationsTo ( concurrentDispatchTasks , defaultOperationsPerDestination ?? emptyDestinationAndOperations , transaction , azureServiceBusTransaction , cancellationToken ) ;
91
+ Task [ ] dispatchTasks =
92
+ [
93
+ DispatchIsolatedOperations ( isolatedOperationsPerDestination ?? emptyDestinationAndOperations , numberOfIsolatedOperations , transaction , azureServiceBusTransaction , cancellationToken ) ,
94
+ DispatchBatchedOperations ( defaultOperationsPerDestination ?? emptyDestinationAndOperations , numberOfDefaultOperations , transaction , azureServiceBusTransaction , cancellationToken )
95
+ ] ;
98
96
99
97
try
100
98
{
101
- await Task . WhenAll ( concurrentDispatchTasks ) . ConfigureAwait ( false ) ;
99
+ await Task . WhenAll ( dispatchTasks ) . ConfigureAwait ( false ) ;
102
100
}
103
101
catch ( Exception ex ) when ( ! ex . IsCausedBy ( cancellationToken ) )
104
102
{
@@ -109,11 +107,18 @@ public async Task Dispatch(TransportOperations outgoingMessages, TransportTransa
109
107
110
108
// The parameters of this method are deliberately mutable and of the original collection type to make sure
111
109
// no boxing occurs
112
- void AddBatchedOperationsTo ( List < Task > dispatchTasks ,
110
+ Task DispatchBatchedOperations (
113
111
Dictionary < string , List < IOutgoingTransportOperation > > transportOperationsPerDestination ,
112
+ int numberOfTransportOperations ,
114
113
TransportTransaction transportTransaction ,
115
114
AzureServiceBusTransportTransaction ? azureServiceBusTransportTransaction , CancellationToken cancellationToken )
116
115
{
116
+ if ( numberOfTransportOperations == 0 )
117
+ {
118
+ return Task . CompletedTask ;
119
+ }
120
+
121
+ var dispatchTasks = new List < Task > ( transportOperationsPerDestination . Count ) ;
117
122
foreach ( var destinationAndOperations in transportOperationsPerDestination )
118
123
{
119
124
var destination = destinationAndOperations . Key ;
@@ -127,9 +132,12 @@ void AddBatchedOperationsTo(List<Task> dispatchTasks,
127
132
messagesToSend . Enqueue ( message ) ;
128
133
}
129
134
// Accessing azureServiceBusTransaction.CommittableTransaction will initialize it if it isn't yet
130
- // doing the access as late as possible but still on the synchronous path.
135
+ // doing the access as late as possible but still on the synchronous path. Initializing the transaction
136
+ // as late as possible is important because it will start the transaction timer. If the transaction
137
+ // is started too early it might shorten the overall transaction time available.
131
138
dispatchTasks . Add ( DispatchBatchOrFallbackToIndividualSendsForDestination ( destination , azureServiceBusTransportTransaction ? . ServiceBusClient , azureServiceBusTransportTransaction ? . Transaction , messagesToSend , cancellationToken ) ) ;
132
139
}
140
+ return Task . WhenAll ( dispatchTasks ) ;
133
141
}
134
142
135
143
async Task DispatchBatchOrFallbackToIndividualSendsForDestination ( string destination , ServiceBusClient ? client , Transaction ? transaction ,
@@ -230,16 +238,23 @@ await Task.WhenAll(individualSendTasks)
230
238
231
239
// The parameters of this method are deliberately mutable and of the original collection type to make sure
232
240
// no boxing occurs
233
- void AddIsolatedOperationsTo ( List < Task > dispatchTasks ,
241
+ Task DispatchIsolatedOperations (
234
242
Dictionary < string , List < IOutgoingTransportOperation > > transportOperationsPerDestination ,
243
+ int numberOfTransportOperations ,
235
244
TransportTransaction transportTransaction ,
236
245
AzureServiceBusTransportTransaction ? azureServiceBusTransportTransaction ,
237
246
CancellationToken cancellationToken )
238
247
{
248
+ if ( numberOfTransportOperations == 0 )
249
+ {
250
+ return Task . CompletedTask ;
251
+ }
252
+
239
253
// It is OK to use the pumps client and partition key (keeps things compliant as before) but
240
254
// isolated dispatches should never use the committable transaction regardless whether it is present
241
255
// or not.
242
256
Transaction ? noTransaction = default ;
257
+ var dispatchTasks = new List < Task > ( numberOfTransportOperations ) ;
243
258
foreach ( var destinationAndOperations in transportOperationsPerDestination )
244
259
{
245
260
var destination = destinationAndOperations . Key ;
@@ -252,6 +267,7 @@ void AddIsolatedOperationsTo(List<Task> dispatchTasks,
252
267
dispatchTasks . Add ( DispatchForDestination ( destination , azureServiceBusTransportTransaction ? . ServiceBusClient , noTransaction , message , cancellationToken ) ) ;
253
268
}
254
269
}
270
+ return Task . WhenAll ( dispatchTasks ) ;
255
271
}
256
272
257
273
async Task DispatchForDestination ( string destination , ServiceBusClient ? client , Transaction ? transaction , ServiceBusMessage message , CancellationToken cancellationToken )
0 commit comments