@@ -40,7 +40,10 @@ public record ClientParameters
40
40
{ "product" , "RabbitMQ Stream" } ,
41
41
{ "version" , Version . VersionString } ,
42
42
{ "platform" , ".NET" } ,
43
- { "copyright" , "Copyright (c) 2017-2023 Broadcom. All Rights Reserved. The term Broadcom refers to Broadcom Inc. and/or its subsidiaries." } ,
43
+ {
44
+ "copyright" ,
45
+ "Copyright (c) 2017-2023 Broadcom. All Rights Reserved. The term Broadcom refers to Broadcom Inc. and/or its subsidiaries."
46
+ } ,
44
47
{
45
48
"information" ,
46
49
"Licensed under the Apache 2.0 and MPL 2.0 licenses. See https://www.rabbitmq.com/"
@@ -53,7 +56,7 @@ public record ClientParameters
53
56
public string VirtualHost { get ; set ; } = "/" ;
54
57
public EndPoint Endpoint { get ; set ; } = new IPEndPoint ( IPAddress . Loopback , 5552 ) ;
55
58
56
- public delegate void MetadataUpdateHandler ( MetaDataUpdate update ) ;
59
+ public delegate Task MetadataUpdateHandler ( MetaDataUpdate update ) ;
57
60
58
61
public event MetadataUpdateHandler OnMetadataUpdate ;
59
62
public Action < Exception > UnhandledExceptionHandler { get ; set ; } = _ => { } ;
@@ -121,12 +124,13 @@ public class Client : IClient
121
124
private readonly TaskCompletionSource < TuneResponse > tuneReceived =
122
125
new TaskCompletionSource < TuneResponse > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
123
126
124
- internal readonly IDictionary < byte , ( Action < ReadOnlyMemory < ulong > > , Action < ( ulong , ResponseCode ) [ ] > ) >
127
+ internal readonly IDictionary < byte , ( string , ( Action < ReadOnlyMemory < ulong > > , Action < ( ulong , ResponseCode ) [ ] > ) ) >
125
128
publishers =
126
- new ConcurrentDictionary < byte , ( Action < ReadOnlyMemory < ulong > > , Action < ( ulong , ResponseCode ) [ ] > ) > ( ) ;
129
+ new ConcurrentDictionary < byte , ( string , ( Action < ReadOnlyMemory < ulong > > , Action < ( ulong , ResponseCode ) [ ] > )
130
+ ) > ( ) ;
127
131
128
- internal readonly IDictionary < byte , ConsumerEvents > consumers =
129
- new ConcurrentDictionary < byte , ConsumerEvents > ( ) ;
132
+ internal readonly IDictionary < byte , ( string , ConsumerEvents ) > consumers =
133
+ new ConcurrentDictionary < byte , ( string , ConsumerEvents ) > ( ) ;
130
134
131
135
private int publishCommandsSent ;
132
136
@@ -312,7 +316,8 @@ public ValueTask<bool> Publish<T>(T msg) where T : struct, ICommand
312
316
313
317
try
314
318
{
315
- publishers . Add ( publisherId , ( confirmCallback , errorCallback ) ) ;
319
+ publishers . Add ( publisherId , ( stream ,
320
+ ( confirmCallback , errorCallback ) ) ) ;
316
321
response = await Request < DeclarePublisherRequest , DeclarePublisherResponse > ( corr =>
317
322
new DeclarePublisherRequest ( corr , publisherId , publisherRef , stream ) ) . ConfigureAwait ( false ) ;
318
323
}
@@ -324,10 +329,9 @@ public ValueTask<bool> Publish<T>(T msg) where T : struct, ICommand
324
329
if ( response . ResponseCode == ResponseCode . Ok )
325
330
return ( publisherId , response ) ;
326
331
327
- // if the response code is not ok we need to remove the subscription
328
332
// and close the connection if necessary.
329
333
publishers . Remove ( publisherId ) ;
330
- await MaybeClose ( "Create Publisher Exception" , stream , pool ) . ConfigureAwait ( false ) ;
334
+ pool ? . MaybeClose ( ClientId , " Publisher creation failed" ) ;
331
335
return ( publisherId , response ) ;
332
336
}
333
337
@@ -396,9 +400,10 @@ private byte IncrementEntityId()
396
400
try
397
401
{
398
402
consumers . Add ( subscriptionId ,
399
- new ConsumerEvents (
400
- deliverHandler ,
401
- consumerUpdateHandler ) ) ;
403
+ ( config . Stream ,
404
+ new ConsumerEvents (
405
+ deliverHandler ,
406
+ consumerUpdateHandler ) ) ) ;
402
407
403
408
response = await Request < SubscribeRequest , SubscribeResponse > ( corr =>
404
409
new SubscribeRequest ( corr , subscriptionId , config . Stream , config . OffsetSpec , initialCredit ,
@@ -412,10 +417,8 @@ private byte IncrementEntityId()
412
417
if ( response . ResponseCode == ResponseCode . Ok )
413
418
return ( subscriptionId , response ) ;
414
419
415
- // if the response code is not ok we need to remove the subscription
416
- // and close the connection if necessary.
417
420
consumers . Remove ( subscriptionId ) ;
418
- await MaybeClose ( "Create Consumer Exception" , config . Stream , config . Pool ) . ConfigureAwait ( false ) ;
421
+ config . Pool . MaybeClose ( ClientId , "Subscription failed" ) ;
419
422
return ( subscriptionId , response ) ;
420
423
}
421
424
@@ -518,7 +521,8 @@ private async Task HandleIncoming(Memory<byte> frameMemory)
518
521
confirmFrames += 1 ;
519
522
if ( publishers . TryGetValue ( confirm . PublisherId , out var publisherConf ) )
520
523
{
521
- var ( confirmCallback , _) = publisherConf ;
524
+ var ( _, ( confirmCallback , _) ) = ( publisherConf ) ;
525
+
522
526
confirmCallback ( confirm . PublishingIds ) ;
523
527
if ( MemoryMarshal . TryGetArray ( confirm . PublishingIds , out var confirmSegment ) )
524
528
{
@@ -542,7 +546,8 @@ private async Task HandleIncoming(Memory<byte> frameMemory)
542
546
Deliver . Read ( frame , out var deliver ) ;
543
547
if ( consumers . TryGetValue ( deliver . SubscriptionId , out var consumerEvent ) )
544
548
{
545
- await consumerEvent . DeliverHandler ( deliver ) . ConfigureAwait ( false ) ;
549
+ var ( _, deliverHandler ) = consumerEvent ;
550
+ await deliverHandler . DeliverHandler ( deliver ) . ConfigureAwait ( false ) ;
546
551
}
547
552
else
548
553
{
@@ -561,7 +566,7 @@ private async Task HandleIncoming(Memory<byte> frameMemory)
561
566
PublishError . Read ( frame , out var error ) ;
562
567
if ( publishers . TryGetValue ( error . PublisherId , out var publisher ) )
563
568
{
564
- var ( _, errorCallback ) = publisher ;
569
+ var ( _, ( _ , errorCallback ) ) = publisher ;
565
570
errorCallback ( error . PublishingErrors ) ;
566
571
}
567
572
else
@@ -588,7 +593,8 @@ private async Task HandleIncoming(Memory<byte> frameMemory)
588
593
ConsumerUpdateQueryResponse . Read ( frame , out var consumerUpdateQueryResponse ) ;
589
594
HandleCorrelatedResponse ( consumerUpdateQueryResponse ) ;
590
595
var consumerEventsUpd = consumers [ consumerUpdateQueryResponse . SubscriptionId ] ;
591
- var off = await consumerEventsUpd . ConsumerUpdateHandler ( consumerUpdateQueryResponse . IsActive )
596
+ var consumer = consumerEventsUpd . Item2 ;
597
+ var off = await consumer . ConsumerUpdateHandler ( consumerUpdateQueryResponse . IsActive )
592
598
. ConfigureAwait ( false ) ;
593
599
if ( off == null )
594
600
{
@@ -736,14 +742,6 @@ private void InternalClose()
736
742
IsClosed = true ;
737
743
}
738
744
739
- private bool HasEntities ( )
740
- {
741
- lock ( Obj )
742
- {
743
- return publishers . Count > 0 || consumers . Count > 0 ;
744
- }
745
- }
746
-
747
745
private async ValueTask < bool > ConsumerUpdateResponse ( uint rCorrelationId , IOffsetType offsetSpecification )
748
746
{
749
747
return await Publish ( new ConsumerUpdateRequest ( rCorrelationId , offsetSpecification ) ) . ConfigureAwait ( false ) ;
@@ -759,6 +757,7 @@ public async Task<CloseResponse> Close(string reason)
759
757
InternalClose ( ) ;
760
758
try
761
759
{
760
+ connection . UpdateCloseStatus ( ConnectionClosedReason . Normal ) ;
762
761
var result =
763
762
await Request < CloseRequest , CloseResponse > ( corr => new CloseRequest ( corr , reason ) ,
764
763
TimeSpan . FromSeconds ( 10 ) ) . ConfigureAwait ( false ) ;
@@ -794,32 +793,14 @@ public async Task<CloseResponse> Close(string reason)
794
793
// Release will decrement the active ids for the connection
795
794
// if the active ids are 0 the connection will be closed
796
795
797
- internal async Task < CloseResponse > MaybeClose ( string reason , string stream , ConnectionsPool pool )
796
+ internal async Task < CloseResponse > MaybeClose ( string reason , ConnectionsPool pool )
798
797
{
799
798
await _poolSemaphore . WaitAsync ( ) . ConfigureAwait ( false ) ;
800
799
try
801
800
{
802
- if ( ! HasEntities ( ) )
803
- {
804
- if ( ! string . IsNullOrEmpty ( ClientId ) )
805
- {
806
- _logger . LogInformation ( "Close connection for the {ClientId}" , ClientId ) ;
807
- // the client can be closed in an unexpected way so we need to remove it from the pool
808
- // so you will find pool.remove(ClientId) also to the disconnect event
809
- pool . Remove ( ClientId ) ;
810
- await Close ( reason ) . ConfigureAwait ( false ) ;
811
- }
812
- }
813
- else
814
- {
815
- // we remove an id reference from the client
816
- // in case there are still active ids from the client and the stream
817
- if ( ! string . IsNullOrEmpty ( ClientId ) )
818
- {
819
- pool . Release ( ClientId , stream ) ;
820
- }
821
- }
822
-
801
+ // the client can be closed in an unexpected way so we need to remove it from the pool
802
+ // so you will find pool.remove(ClientId) also to the disconnect event
803
+ pool . MaybeClose ( ClientId , reason ) ;
823
804
var result = new CloseResponse ( 0 , ResponseCode . Ok ) ;
824
805
return result ;
825
806
}
@@ -831,6 +812,16 @@ internal async Task<CloseResponse> MaybeClose(string reason, string stream, Conn
831
812
832
813
public string ClientId { get ; init ; }
833
814
815
+ public IDictionary < byte , ( string , ( Action < ReadOnlyMemory < ulong > > , Action < ( ulong , ResponseCode ) [ ] > ) ) > Publishers
816
+ {
817
+ get => publishers ;
818
+ }
819
+
820
+ public IDictionary < byte , ( string , ConsumerEvents ) > Consumers
821
+ {
822
+ get => consumers ;
823
+ }
824
+
834
825
public async ValueTask < QueryPublisherResponse > QueryPublisherSequence ( string publisherRef , string stream )
835
826
{
836
827
return await Request < QueryPublisherRequest , QueryPublisherResponse > ( corr =>
0 commit comments