30
30
//---------------------------------------------------------------------------
31
31
32
32
using System ;
33
- using System . Buffers . Binary ;
34
33
using System . Collections . Generic ;
35
34
using System . Diagnostics ;
36
35
using System . Text ;
37
36
using System . Threading ;
38
37
using System . Threading . Tasks ;
39
38
using RabbitMQ . Client ;
39
+ using RabbitMQ . Client . Exceptions ;
40
40
41
41
const ushort MAX_OUTSTANDING_CONFIRMS = 256 ;
42
42
@@ -124,11 +124,33 @@ async Task PublishMessagesInBatchAsync()
124
124
var sw = new Stopwatch ( ) ;
125
125
sw . Start ( ) ;
126
126
127
+ channel . BasicReturnAsync += ( sender , ea ) =>
128
+ {
129
+ ulong sequenceNumber = 0 ;
130
+
131
+ IReadOnlyBasicProperties props = ea . BasicProperties ;
132
+ if ( props . Headers is not null )
133
+ {
134
+ object ? maybeSeqNum = props . Headers [ Constants . PublishSequenceNumberHeader ] ;
135
+ if ( maybeSeqNum is long longSequenceNumber )
136
+ {
137
+ sequenceNumber = ( ulong ) longSequenceNumber ;
138
+ }
139
+ }
140
+
141
+ return Console . Out . WriteLineAsync ( $ "{ DateTime . Now } [INFO] message sequence number '{ sequenceNumber } ' has been basic.return-ed") ;
142
+ } ;
143
+
127
144
var publishTasks = new List < ValueTask > ( ) ;
128
145
for ( int i = 0 ; i < MESSAGE_COUNT ; i ++ )
129
146
{
147
+ string rk = queueName ;
148
+ if ( i % 1000 == 0 )
149
+ {
150
+ rk = Guid . NewGuid ( ) . ToString ( ) ;
151
+ }
130
152
byte [ ] body = Encoding . UTF8 . GetBytes ( i . ToString ( ) ) ;
131
- publishTasks . Add ( channel . BasicPublishAsync ( exchange : string . Empty , routingKey : queueName , body : body , mandatory : true , basicProperties : props ) ) ;
153
+ publishTasks . Add ( channel . BasicPublishAsync ( exchange : string . Empty , routingKey : rk , body : body , mandatory : true , basicProperties : props ) ) ;
132
154
outstandingMessageCount ++ ;
133
155
134
156
if ( outstandingMessageCount == batchSize )
@@ -139,9 +161,13 @@ async Task PublishMessagesInBatchAsync()
139
161
{
140
162
await pt ;
141
163
}
164
+ catch ( PublishException pex )
165
+ {
166
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return, pex.IsReturn: '{ pex . IsReturn } ', seq no: '{ pex . PublishSequenceNumber } '") ;
167
+ }
142
168
catch ( Exception ex )
143
169
{
144
- Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return , ex: '{ ex } '") ;
170
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw exception , ex: '{ ex } '") ;
145
171
}
146
172
}
147
173
publishTasks . Clear ( ) ;
@@ -157,9 +183,13 @@ async Task PublishMessagesInBatchAsync()
157
183
{
158
184
await pt ;
159
185
}
186
+ catch ( PublishException pex )
187
+ {
188
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return, pex.IsReturn: '{ pex . IsReturn } ', seq no: '{ pex . PublishSequenceNumber } '") ;
189
+ }
160
190
catch ( Exception ex )
161
191
{
162
- Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return , ex: '{ ex } '") ;
192
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw exception , ex: '{ ex } '") ;
163
193
}
164
194
}
165
195
publishTasks . Clear ( ) ;
@@ -236,22 +266,23 @@ async Task CleanOutstandingConfirms(ulong deliveryTag, bool multiple)
236
266
}
237
267
}
238
268
239
- channel . BasicReturnAsync += ( sender , ea ) =>
269
+ channel . BasicReturnAsync += async ( sender , ea ) =>
240
270
{
241
271
ulong sequenceNumber = 0 ;
242
272
243
273
IReadOnlyBasicProperties props = ea . BasicProperties ;
244
274
if ( props . Headers is not null )
245
275
{
246
276
object ? maybeSeqNum = props . Headers [ Constants . PublishSequenceNumberHeader ] ;
247
- if ( maybeSeqNum is not null )
277
+ if ( maybeSeqNum is long longSequenceNumber )
248
278
{
249
- sequenceNumber = BinaryPrimitives . ReadUInt64BigEndian ( ( byte [ ] ) maybeSeqNum ) ;
279
+ sequenceNumber = ( ulong ) longSequenceNumber ;
250
280
}
251
281
}
252
282
253
- Console . WriteLine ( $ "{ DateTime . Now } [WARNING] message sequence number { sequenceNumber } has been basic.return-ed") ;
254
- return CleanOutstandingConfirms ( sequenceNumber , false ) ;
283
+ await Console . Out . WriteLineAsync ( $ "{ DateTime . Now } [INFO] message sequence number '{ sequenceNumber } ' has been basic.return-ed") ;
284
+
285
+ await CleanOutstandingConfirms ( sequenceNumber , false ) ;
255
286
} ;
256
287
257
288
channel . BasicAcksAsync += ( sender , ea ) => CleanOutstandingConfirms ( ea . DeliveryTag , ea . Multiple ) ;
@@ -290,13 +321,21 @@ async Task CleanOutstandingConfirms(ulong deliveryTag, bool multiple)
290
321
// This will cause a basic.return, for fun
291
322
rk = Guid . NewGuid ( ) . ToString ( ) ;
292
323
}
324
+
325
+ var msgProps = new BasicProperties
326
+ {
327
+ Persistent = true ,
328
+ Headers = new Dictionary < string , object ? > ( )
329
+ } ;
330
+
331
+ msgProps . Headers . Add ( Constants . PublishSequenceNumberHeader , ( long ) nextPublishSeqNo ) ;
332
+
293
333
( ulong , ValueTask ) data =
294
- ( nextPublishSeqNo , channel . BasicPublishAsync ( exchange : string . Empty , routingKey : rk , body : body , mandatory : true , basicProperties : props ) ) ;
334
+ ( nextPublishSeqNo , channel . BasicPublishAsync ( exchange : string . Empty , routingKey : rk , body : body , mandatory : true , basicProperties : msgProps ) ) ;
295
335
publishTasks . Add ( data ) ;
296
336
}
297
337
298
338
using var cts = new CancellationTokenSource ( TimeSpan . FromSeconds ( 10 ) ) ;
299
- // await Task.WhenAll(publishTasks).WaitAsync(cts.Token);
300
339
foreach ( ( ulong SeqNo , ValueTask PublishTask ) datum in publishTasks )
301
340
{
302
341
try
0 commit comments