11using System ;
22using System . Collections . Concurrent ;
33using System . Diagnostics . CodeAnalysis ;
4+ using System . Diagnostics . SymbolStore ;
45using System . Net ;
56using System . Threading ;
67using System . Threading . Tasks ;
@@ -13,7 +14,7 @@ namespace StackExchange.Redis
1314 public partial class ConnectionMultiplexer
1415 {
1516 private RedisSubscriber ? _defaultSubscriber ;
16- private RedisSubscriber DefaultSubscriber => _defaultSubscriber ??= new RedisSubscriber ( this , null ) ;
17+ internal RedisSubscriber DefaultSubscriber => _defaultSubscriber ??= new RedisSubscriber ( this , null ) ;
1718
1819 private readonly ConcurrentDictionary < RedisChannel , Subscription > subscriptions = new ( ) ;
1920
@@ -282,6 +283,17 @@ internal void GetSubscriberCounts(out int handlers, out int queues)
282283
283284 internal ServerEndPoint ? GetCurrentServer ( ) => Volatile . Read ( ref CurrentServer ) ;
284285 internal void SetCurrentServer ( ServerEndPoint ? server ) => CurrentServer = server ;
286+ // conditional clear
287+ internal bool ClearCurrentServer ( ServerEndPoint expected )
288+ {
289+ if ( CurrentServer == expected )
290+ {
291+ CurrentServer = null ;
292+ return true ;
293+ }
294+
295+ return false ;
296+ }
285297
286298 /// <summary>
287299 /// Evaluates state and if we're not currently connected, clears the server reference.
@@ -425,6 +437,27 @@ internal bool EnsureSubscribedToServer(Subscription sub, RedisChannel channel, C
425437 return ExecuteSync ( message , sub . Processor , selected ) ;
426438 }
427439
440+ internal void ResubscribeToServer ( Subscription sub , RedisChannel channel , ServerEndPoint serverEndPoint , string cause )
441+ {
442+ // conditional: only if that's the server we were connected to, or "none"; we don't want to end up duplicated
443+ if ( sub . ClearCurrentServer ( serverEndPoint ) || ! sub . IsConnected )
444+ {
445+ if ( serverEndPoint . IsSubscriberConnected )
446+ {
447+ // we'll *try* for a simple resubscribe, following any -MOVED etc, but if that fails: fall back
448+ // to full reconfigure; importantly, note that we've already recorded the disconnect
449+ var message = sub . GetMessage ( channel , SubscriptionAction . Subscribe , CommandFlags . None , false ) ;
450+ _ = ExecuteAsync ( message , sub . Processor , serverEndPoint ) . ContinueWith (
451+ t => multiplexer . ReconfigureIfNeeded ( serverEndPoint . EndPoint , false , cause : cause ) ,
452+ TaskContinuationOptions . OnlyOnFaulted ) ;
453+ }
454+ else
455+ {
456+ multiplexer . ReconfigureIfNeeded ( serverEndPoint . EndPoint , false , cause : cause ) ;
457+ }
458+ }
459+ }
460+
428461 Task ISubscriber . SubscribeAsync ( RedisChannel channel , Action < RedisChannel , RedisValue > handler , CommandFlags flags )
429462 => SubscribeAsync ( channel , handler , null , flags ) ;
430463
0 commit comments