@@ -104,10 +104,7 @@ public async ValueTask<ServerSession> GetSessionAsync(MySqlConnection connection
104104 }
105105
106106 // create a new session
107- session = new ( this , m_generation , Interlocked . Increment ( ref m_lastSessionId ) ) ;
108- if ( Log . IsInfoEnabled ( ) )
109- Log . Info ( "Pool{0} no pooled session available; created new Session{1}" , m_logArguments [ 0 ] , session . Id ) ;
110- await session . ConnectAsync ( ConnectionSettings , startTickCount , m_loadBalancer , ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
107+ session = await ConnectSessionAsync ( "Pool{0} no pooled session available; created new Session{1}" , startTickCount , ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
111108 AdjustHostConnectionCount ( session , 1 ) ;
112109 session . OwningConnection = new ( connection ) ;
113110 int leasedSessionsCountNew ;
@@ -350,9 +347,7 @@ private async Task CreateMinimumPooledSessions(IOBehavior ioBehavior, Cancellati
350347
351348 try
352349 {
353- var session = new ServerSession ( this , m_generation , Interlocked . Increment ( ref m_lastSessionId ) ) ;
354- Log . Info ( "Pool{0} created Session{1} to reach minimum pool size" , m_logArguments [ 0 ] , session . Id ) ;
355- await session . ConnectAsync ( ConnectionSettings , Environment . TickCount , m_loadBalancer , ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
350+ var session = await ConnectSessionAsync ( "Pool{0} created Session{1} to reach minimum pool size" , Environment . TickCount , ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
356351 AdjustHostConnectionCount ( session , 1 ) ;
357352 lock ( m_sessions )
358353 m_sessions . AddFirst ( session ) ;
@@ -365,6 +360,42 @@ private async Task CreateMinimumPooledSessions(IOBehavior ioBehavior, Cancellati
365360 }
366361 }
367362
363+ private async ValueTask < ServerSession > ConnectSessionAsync ( string logMessage , int startTickCount , IOBehavior ioBehavior , CancellationToken cancellationToken )
364+ {
365+ var session = new ServerSession ( this , m_generation , Interlocked . Increment ( ref m_lastSessionId ) ) ;
366+ if ( Log . IsInfoEnabled ( ) )
367+ Log . Info ( logMessage , m_logArguments [ 0 ] , session . Id ) ;
368+ var statusInfo = await session . ConnectAsync ( ConnectionSettings , startTickCount , m_loadBalancer , ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
369+
370+ if ( statusInfo is not null && statusInfo . StartsWith ( "Location: mysql://" , StringComparison . Ordinal ) )
371+ {
372+ // server redirection string has the format "Location: mysql://{host}:{port}/user={userId}[&ttl={ttl}]"
373+ Log . Info ( "Session{0} has server redirection header {1}" , session . Id , statusInfo ) ;
374+
375+ if ( Utility . TryParseRedirectionHeader ( statusInfo , out var host , out var port , out var user ) )
376+ {
377+ Log . Info ( "Session{0} found server redirection Host={1}; Port={2}; User={3}" , session . Id , host , port , user ) ;
378+
379+ if ( host != ConnectionSettings . HostNames ! [ 0 ] || port != ConnectionSettings . Port || user != ConnectionSettings . UserID )
380+ {
381+ var redirectedSettings = ConnectionSettings . CloneWith ( host , port , user ) ;
382+ Log . Info ( "Pool{0} opening new connection to Host={1}; Port={2}; User={3}" , m_logArguments [ 0 ] , host , port , user ) ;
383+ var redirectedSession = new ServerSession ( this , m_generation , Interlocked . Increment ( ref m_lastSessionId ) ) ;
384+ await redirectedSession . ConnectAsync ( redirectedSettings , startTickCount , m_loadBalancer , ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
385+ Log . Info ( "Pool{0} closing Session{1} to use redirected Session{2} instead" , m_logArguments [ 0 ] , session . Id , redirectedSession . Id ) ;
386+ await session . DisposeAsync ( ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
387+ return redirectedSession ;
388+ }
389+ else
390+ {
391+ Log . Info ( "Session{0} is already connected to this server; ignoring redirection" , session . Id ) ;
392+ }
393+ }
394+ }
395+
396+ return session ;
397+ }
398+
368399 public static ConnectionPool ? GetPool ( string connectionString )
369400 {
370401 // check single-entry MRU cache for this exact connection string; most applications have just one
0 commit comments