11using System ;
22using System . Collections . Generic ;
3+ using System . Diagnostics ;
34using System . Linq ;
5+ using System . Threading ;
46using ServiceStack . Logging ;
57
68namespace ServiceStack . Redis
@@ -74,68 +76,95 @@ public virtual void ResetSlaves(List<RedisEndpoint> newSlaves)
7476 log . Debug ( "New Redis Slaves: " + string . Join ( ", " , slaves . Map ( x => x . GetHostString ( ) ) ) ) ;
7577 }
7678
79+ public RedisEndpoint GetReadWriteHost ( int desiredIndex )
80+ {
81+ return sentinel . GetMaster ( ) ?? masters [ desiredIndex % masters . Length ] ;
82+ }
83+
84+ public RedisEndpoint GetReadOnlyHost ( int desiredIndex )
85+ {
86+ var slavesEndpoints = sentinel . GetSlaves ( ) ;
87+ if ( slavesEndpoints . Count > 0 )
88+ return slavesEndpoints [ desiredIndex % slavesEndpoints . Count ] ;
89+
90+ return ReadOnlyHostsCount > 0
91+ ? slaves [ desiredIndex % slaves . Length ]
92+ : GetReadWriteHost ( desiredIndex ) ;
93+ }
94+
7795 public virtual RedisClient CreateRedisClient ( RedisEndpoint config , bool readWrite )
7896 {
7997 var client = RedisConfig . ClientFactory ( config ) ;
8098
81- if ( readWrite && RedisConfig . VerifyMasterConnections )
99+ if ( readWrite )
82100 {
83101 var role = client . GetServerRole ( ) ;
84102 if ( role != RedisServerRole . Master )
85103 {
86- log . Error ( "Redis Master Host '{0}' is {1}. Resetting allHosts..." . Fmt ( config . GetHostString ( ) , role ) ) ;
87- var newMasters = new List < RedisEndpoint > ( ) ;
88- var newSlaves = new List < RedisEndpoint > ( ) ;
89- RedisClient masterClient = null ;
90- foreach ( var hostConfig in allHosts )
104+ try
105+ {
106+ var stopwatch = Stopwatch . StartNew ( ) ;
107+ while ( true )
108+ {
109+ var masterConfig = sentinel . GetMaster ( ) ;
110+ var master = RedisConfig . ClientFactory ( masterConfig ) ;
111+ var masterRole = master . GetServerRole ( ) ;
112+ if ( masterRole == RedisServerRole . Master )
113+ return master ;
114+
115+ if ( stopwatch . Elapsed > sentinel . MaxWaitBetweenSentinelLookups )
116+ throw new TimeoutException ( "Max Wait Between Sentinel Lookups Elapsed: {0}"
117+ . Fmt ( sentinel . MaxWaitBetweenSentinelLookups . ToString ( ) ) ) ;
118+
119+ Thread . Sleep ( sentinel . WaitBetweenSentinelLookups ) ;
120+ }
121+ }
122+ catch ( Exception ex )
91123 {
92- try
124+ log . Error ( "Redis Master Host '{0}' is {1}. Resetting allHosts..." . Fmt ( config . GetHostString ( ) , role ) , ex ) ;
125+ var newMasters = new List < RedisEndpoint > ( ) ;
126+ var newSlaves = new List < RedisEndpoint > ( ) ;
127+ RedisClient masterClient = null ;
128+ foreach ( var hostConfig in allHosts )
93129 {
94- var testClient = new RedisClient ( hostConfig ) {
95- ConnectTimeout = RedisConfig . SentinelConnectTimeout
96- } ;
97- var testRole = testClient . GetServerRole ( ) ;
98- switch ( testRole )
130+ try
99131 {
100- case RedisServerRole . Master :
101- newMasters . Add ( hostConfig ) ;
102- if ( masterClient == null )
103- masterClient = testClient ;
104- break ;
105- case RedisServerRole . Slave :
106- newSlaves . Add ( hostConfig ) ;
107- break ;
132+ var testClient = new RedisClient ( hostConfig )
133+ {
134+ ConnectTimeout = RedisConfig . HostLookupTimeout
135+ } ;
136+ var testRole = testClient . GetServerRole ( ) ;
137+ switch ( testRole )
138+ {
139+ case RedisServerRole . Master :
140+ newMasters . Add ( hostConfig ) ;
141+ if ( masterClient == null )
142+ masterClient = testClient ;
143+ break ;
144+ case RedisServerRole . Slave :
145+ newSlaves . Add ( hostConfig ) ;
146+ break ;
147+ }
148+
108149 }
150+ catch { /* skip */ }
151+ }
109152
153+ if ( masterClient == null )
154+ {
155+ var errorMsg = "No master found in: " + string . Join ( ", " , allHosts . Map ( x => x . GetHostString ( ) ) ) ;
156+ log . Error ( errorMsg ) ;
157+ throw new Exception ( errorMsg ) ;
110158 }
111- catch { /* skip */ }
112- }
113159
114- if ( masterClient == null )
115- {
116- var errorMsg = "No master found in: " + string . Join ( ", " , allHosts . Map ( x => x . GetHostString ( ) ) ) ;
117- log . Error ( errorMsg ) ;
118- throw new Exception ( errorMsg ) ;
160+ ResetMasters ( newMasters ) ;
161+ ResetSlaves ( newSlaves ) ;
162+ return masterClient ;
119163 }
120-
121- ResetMasters ( newMasters ) ;
122- ResetSlaves ( newSlaves ) ;
123- return masterClient ;
124164 }
125165 }
126166
127167 return client ;
128168 }
129-
130- public RedisEndpoint GetReadWriteHost ( int desiredIndex )
131- {
132- return masters [ desiredIndex % masters . Length ] ;
133- }
134-
135- public RedisEndpoint GetReadOnlyHost ( int desiredIndex )
136- {
137- return ReadOnlyHostsCount > 0
138- ? slaves [ desiredIndex % slaves . Length ]
139- : GetReadWriteHost ( desiredIndex ) ;
140- } }
169+ }
141170}
0 commit comments