@@ -17,14 +17,26 @@ namespace RabbitMQ.Stream.Client.Reliable;
1717/// <param name="Stream"> Stream or SuperSuper affected</param>
1818/// <param name="Identifier"> The Entity Identifier </param>
1919/// <param name="Partition"> Super stream partition. Valid only for SuperStream else is empty</param>
20+ /// <param name="Reason"> The reason why the status changed </param>
2021public record StatusInfo (
21- ReliableEntityStatus From ,
22- ReliableEntityStatus To ,
22+ ReliableEntityStatus From , // init
23+ ReliableEntityStatus To , // open
2324 string Stream ,
2425 string Identifier ,
25- string Partition
26+ string Partition ,
27+ ChangeStatusReason Reason = ChangeStatusReason . None
2628) ;
2729
30+ public enum ChangeStatusReason
31+ {
32+ None ,
33+ UnexpectedlyDisconnected ,
34+ MetaDataUpdate ,
35+ ClosedByUser ,
36+ ClosedByStrategyPolicy ,
37+ BoolFailure
38+ }
39+
2840public record ReliableConfig
2941{
3042 /// <summary>
@@ -81,8 +93,7 @@ public enum ReliableEntityStatus
8193{
8294 Initialization , // the entity is initializing
8395 Open , // the entity is open and ready to use
84- ReconnectionForUnexpectedlyDisconnected , // the entity is disconnected in an unexpected way but still considered open
85- ReconnectionForMetaDataUpdate , // the entity is disconnected because the stream topology has changed but still considered open
96+ Reconnection , // the entity is in reconnection but it is still considered open
8697 Closed , // the entity is closed and cannot be used anymore
8798}
8899
@@ -103,7 +114,8 @@ protected static async Task RandomWait()
103114 await Task . Delay ( Consts . RandomMid ( ) ) . ConfigureAwait ( false ) ;
104115 }
105116
106- protected void UpdateStatus ( ReliableEntityStatus newStatus , string partition = null )
117+ protected void UpdateStatus ( ReliableEntityStatus newStatus ,
118+ ChangeStatusReason reason , string partition = null )
107119 {
108120 var oldStatus = _status ;
109121 lock ( _lock )
@@ -113,7 +125,7 @@ protected void UpdateStatus(ReliableEntityStatus newStatus, string partition = n
113125 {
114126 _reliableConfig . OnStatusChanged ( new StatusInfo ( oldStatus , newStatus ,
115127 _reliableConfig . Stream ,
116- _reliableConfig . Identifier , partition ) ) ;
128+ _reliableConfig . Identifier , partition , reason ) ) ;
117129 }
118130 }
119131 }
@@ -150,7 +162,7 @@ private async Task MaybeInit(bool boot)
150162 // else there are two ways:
151163 // - the exception is a known exception and the client will try to reconnect
152164 // - the exception is not a known exception and the client will throw the exception
153- UpdateStatus ( ReliableEntityStatus . Open ) ;
165+ UpdateStatus ( ReliableEntityStatus . Open , ChangeStatusReason . None ) ;
154166 }
155167 catch ( Exception e )
156168 {
@@ -159,7 +171,7 @@ private async Task MaybeInit(bool boot)
159171 BaseLogger . LogError ( "{Identity} Error during the first boot {EMessage}" ,
160172 ToString ( ) , e . Message ) ;
161173 // if it is the first boot we don't need to reconnect
162- UpdateStatus ( ReliableEntityStatus . Closed ) ;
174+ UpdateStatus ( ReliableEntityStatus . Closed , ChangeStatusReason . BoolFailure ) ;
163175 throw ;
164176 }
165177
@@ -188,7 +200,7 @@ private async Task Init(bool boot)
188200 // each time that the client is initialized, we need to reset the status
189201 // if we hare here it means that the entity is not open for some reason like:
190202 // first time initialization or reconnect due of a IsAKnownException
191- UpdateStatus ( ReliableEntityStatus . Initialization ) ;
203+ UpdateStatus ( ReliableEntityStatus . Initialization , ChangeStatusReason . None ) ;
192204
193205 await SemaphoreSlim . WaitAsync ( ) . ConfigureAwait ( false ) ;
194206 try
@@ -275,7 +287,7 @@ private async Task MaybeReconnect()
275287 if ( ! reconnect )
276288 {
277289 BaseLogger . LogDebug ( "{Identity} is closed due of reconnect strategy" , ToString ( ) ) ;
278- UpdateStatus ( ReliableEntityStatus . Closed ) ;
290+ UpdateStatus ( ReliableEntityStatus . Closed , ChangeStatusReason . ClosedByStrategyPolicy ) ;
279291 return ;
280292 }
281293
@@ -285,8 +297,7 @@ private async Task MaybeReconnect()
285297 await MaybeInit ( false ) . ConfigureAwait ( false ) ;
286298 break ;
287299 case false :
288- if ( CompareStatus ( ReliableEntityStatus . ReconnectionForMetaDataUpdate ) ||
289- CompareStatus ( ReliableEntityStatus . ReconnectionForUnexpectedlyDisconnected ) )
300+ if ( CompareStatus ( ReliableEntityStatus . Reconnection ) )
290301 {
291302 BaseLogger . LogDebug ( "{Identity} is in Reconnecting" , ToString ( ) ) ;
292303 }
@@ -304,14 +315,14 @@ private async Task MaybeReconnectPartition(StreamInfo streamInfo, string info,
304315 if ( ! reconnect )
305316 {
306317 BaseLogger . LogDebug ( "{Identity} partition is closed due of reconnect strategy" , ToString ( ) ) ;
307- UpdateStatus ( ReliableEntityStatus . Closed , streamInfo . Stream ) ;
318+ UpdateStatus ( ReliableEntityStatus . Closed , ChangeStatusReason . ClosedByStrategyPolicy , streamInfo . Stream ) ;
308319 return ;
309320 }
310321
311322 try
312323 {
313324 await reconnectPartitionFunc ( streamInfo ) . ConfigureAwait ( false ) ;
314- UpdateStatus ( ReliableEntityStatus . Open , streamInfo . Stream ) ;
325+ UpdateStatus ( ReliableEntityStatus . Open , ChangeStatusReason . None , streamInfo . Stream ) ;
315326 await _reliableConfig . ReconnectStrategy . WhenConnected (
316327 $ "Super Stream partition: { streamInfo . Stream } for { info } ") . ConfigureAwait ( false ) ;
317328 }
@@ -353,11 +364,12 @@ private void LogException(Exception exception)
353364 /// <param name="reconnectPartitionFunc">Function to reconnect the partition</param>
354365 /// <param name="reason">The reason why the connection is closed (Metadata update od disconnection)</param>
355366 internal async Task OnEntityClosed ( StreamSystem system , string stream ,
356- Func < StreamInfo , Task > reconnectPartitionFunc , ReliableEntityStatus reason )
367+ Func < StreamInfo , Task > reconnectPartitionFunc , ChangeStatusReason reason )
357368 {
358369 var streamExists = false ;
359370 await SemaphoreSlim . WaitAsync ( ) . ConfigureAwait ( false ) ;
360- UpdateStatus ( reason , stream ) ;
371+ UpdateStatus ( ReliableEntityStatus . Reconnection , reason ,
372+ stream ) ;
361373 try
362374 {
363375 streamExists = await CheckIfStreamIsAvailable ( stream , system )
@@ -385,11 +397,11 @@ internal async Task OnEntityClosed(StreamSystem system, string stream,
385397 /// <param name="system">Stream system</param>
386398 /// <param name="stream">Stream</param>
387399 /// <param name="reason">The reason why the connection is closed (Metadata update od disconnection)</param>
388- internal async Task OnEntityClosed ( StreamSystem system , string stream , ReliableEntityStatus reason )
400+ internal async Task OnEntityClosed ( StreamSystem system , string stream , ChangeStatusReason reason )
389401 {
390402 var streamExists = false ;
391403 await SemaphoreSlim . WaitAsync ( ) . ConfigureAwait ( false ) ;
392- UpdateStatus ( reason , stream ) ;
404+ UpdateStatus ( ReliableEntityStatus . Reconnection , reason , stream ) ;
393405 try
394406 {
395407 streamExists = await CheckIfStreamIsAvailable ( stream , system )
0 commit comments