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
54
54
Persistent = true
55
55
} ;
56
56
57
- string hostname = "localhost " ;
57
+ string hostname = "shostakovich " ;
58
58
if ( args . Length > 0 )
59
59
{
60
60
if ( false == string . IsNullOrWhiteSpace ( args [ 0 ] ) )
@@ -124,11 +124,43 @@ async Task PublishMessagesInBatchAsync()
124
124
var sw = new Stopwatch ( ) ;
125
125
sw . Start ( ) ;
126
126
127
+ channel . BasicReturnAsync += ( sender , ea ) =>
128
+ {
129
+ string sequenceNumber = string . Empty ;
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 not null )
136
+ {
137
+ switch ( maybeSeqNum )
138
+ {
139
+ case byte [ ] seqNumBytes :
140
+ sequenceNumber = Encoding . ASCII . GetString ( seqNumBytes ) ;
141
+ break ;
142
+ case string seqNumStr :
143
+ sequenceNumber = seqNumStr ;
144
+ break ;
145
+ }
146
+ }
147
+ }
148
+
149
+ Console . WriteLine ( $ "{ DateTime . Now } [WARNING] message sequence number { sequenceNumber } has been basic.return-ed") ;
150
+
151
+ return Task . CompletedTask ;
152
+ } ;
153
+
127
154
var publishTasks = new List < ValueTask > ( ) ;
128
155
for ( int i = 0 ; i < MESSAGE_COUNT ; i ++ )
129
156
{
157
+ string rk = queueName ;
158
+ if ( i % 1000 == 0 )
159
+ {
160
+ rk = Guid . NewGuid ( ) . ToString ( ) ;
161
+ }
130
162
byte [ ] body = Encoding . UTF8 . GetBytes ( i . ToString ( ) ) ;
131
- publishTasks . Add ( channel . BasicPublishAsync ( exchange : string . Empty , routingKey : queueName , body : body , mandatory : true , basicProperties : props ) ) ;
163
+ publishTasks . Add ( channel . BasicPublishAsync ( exchange : string . Empty , routingKey : rk , body : body , mandatory : true , basicProperties : props ) ) ;
132
164
outstandingMessageCount ++ ;
133
165
134
166
if ( outstandingMessageCount == batchSize )
@@ -139,9 +171,13 @@ async Task PublishMessagesInBatchAsync()
139
171
{
140
172
await pt ;
141
173
}
174
+ catch ( PublishException pex )
175
+ {
176
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return, pex.IsReturn: '{ pex . IsReturn } ', seq no: '{ pex . PublishSequenceNumber } '") ;
177
+ }
142
178
catch ( Exception ex )
143
179
{
144
- Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return , ex: '{ ex } '") ;
180
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw exception , ex: '{ ex } '") ;
145
181
}
146
182
}
147
183
publishTasks . Clear ( ) ;
@@ -157,9 +193,13 @@ async Task PublishMessagesInBatchAsync()
157
193
{
158
194
await pt ;
159
195
}
196
+ catch ( PublishException pex )
197
+ {
198
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return, pex.IsReturn: '{ pex . IsReturn } ', seq no: '{ pex . PublishSequenceNumber } '") ;
199
+ }
160
200
catch ( Exception ex )
161
201
{
162
- Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw nack or return , ex: '{ ex } '") ;
202
+ Console . Error . WriteLine ( $ "{ DateTime . Now } [ERROR] saw exception , ex: '{ ex } '") ;
163
203
}
164
204
}
165
205
publishTasks . Clear ( ) ;
@@ -244,13 +284,14 @@ async Task CleanOutstandingConfirms(ulong deliveryTag, bool multiple)
244
284
if ( props . Headers is not null )
245
285
{
246
286
object ? maybeSeqNum = props . Headers [ Constants . PublishSequenceNumberHeader ] ;
247
- if ( maybeSeqNum is not null )
287
+ if ( maybeSeqNum is long longSequenceNumber )
248
288
{
249
- sequenceNumber = BinaryPrimitives . ReadUInt64BigEndian ( ( byte [ ] ) maybeSeqNum ) ;
289
+ sequenceNumber = ( ulong ) longSequenceNumber ;
250
290
}
251
291
}
252
292
253
- Console . WriteLine ( $ "{ DateTime . Now } [WARNING] message sequence number { sequenceNumber } has been basic.return-ed") ;
293
+ Console . WriteLine ( $ "{ DateTime . Now } [INFO] message sequence number '{ sequenceNumber } ' has been basic.return-ed") ;
294
+
254
295
return CleanOutstandingConfirms ( sequenceNumber , false ) ;
255
296
} ;
256
297
@@ -290,13 +331,21 @@ async Task CleanOutstandingConfirms(ulong deliveryTag, bool multiple)
290
331
// This will cause a basic.return, for fun
291
332
rk = Guid . NewGuid ( ) . ToString ( ) ;
292
333
}
334
+
335
+ var msgProps = new BasicProperties
336
+ {
337
+ Persistent = true ,
338
+ Headers = new Dictionary < string , object ? > ( )
339
+ } ;
340
+
341
+ msgProps . Headers . Add ( Constants . PublishSequenceNumberHeader , ( long ) nextPublishSeqNo ) ;
342
+
293
343
( ulong , ValueTask ) data =
294
- ( nextPublishSeqNo , channel . BasicPublishAsync ( exchange : string . Empty , routingKey : rk , body : body , mandatory : true , basicProperties : props ) ) ;
344
+ ( nextPublishSeqNo , channel . BasicPublishAsync ( exchange : string . Empty , routingKey : rk , body : body , mandatory : true , basicProperties : msgProps ) ) ;
295
345
publishTasks . Add ( data ) ;
296
346
}
297
347
298
348
using var cts = new CancellationTokenSource ( TimeSpan . FromSeconds ( 10 ) ) ;
299
- // await Task.WhenAll(publishTasks).WaitAsync(cts.Token);
300
349
foreach ( ( ulong SeqNo , ValueTask PublishTask ) datum in publishTasks )
301
350
{
302
351
try
0 commit comments