Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 97bfdd5

Browse files
committed
Change pool handling in new RedisManagerPool, return new (unmanaged) client when pool exceeded instead of blocking
1 parent b67eb8b commit 97bfdd5

File tree

3 files changed

+34
-37
lines changed

3 files changed

+34
-37
lines changed

src/ServiceStack.Redis/RedisManagerPool.cs

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,13 @@ namespace ServiceStack.Redis
1111
{
1212
public class RedisPoolConfig
1313
{
14-
public const int DefaultPoolTimeoutMs = 2000;
15-
public const int DefaultMaxPoolSize = 50;
14+
public const int DefaultMaxPoolSize = 20;
1615

1716
public RedisPoolConfig()
1817
{
1918
MaxPoolSize = DefaultMaxPoolSize;
20-
PoolTimeout = TimeSpan.FromMilliseconds(DefaultPoolTimeoutMs);
2119
}
2220

23-
public TimeSpan PoolTimeout { get; set; }
2421
public int MaxPoolSize { get; set; }
2522
}
2623

@@ -50,7 +47,6 @@ public partial class RedisManagerPool
5047

5148
public Action<IRedisNativeClient> ConnectionFilter { get; set; }
5249

53-
public int PoolTimeoutMs { get; set; }
5450
public int MaxPoolSize { get; set; }
5551

5652
public RedisManagerPool() : this(RedisNativeClient.DefaultHost) {}
@@ -74,7 +70,6 @@ public RedisManagerPool(IEnumerable<string> hosts, RedisPoolConfig config)
7470

7571
this.OnFailover = new List<Action<IRedisClientsManager>>();
7672

77-
this.PoolTimeoutMs = (int) config.PoolTimeout.TotalMilliseconds;
7873
this.MaxPoolSize = config.MaxPoolSize;
7974

8075
clients = new RedisClient[MaxPoolSize];
@@ -121,9 +116,13 @@ public IRedisClient GetClient()
121116
RedisClient inActiveClient;
122117
while ((inActiveClient = GetInActiveClient()) == null)
123118
{
124-
// wait for a connection, cry out if made to wait too long
125-
if (!Monitor.Wait(clients, PoolTimeoutMs))
126-
throw new TimeoutException(PoolTimeoutError);
119+
//Create new client outside of pool when max pool size exceeded
120+
var nextIndex = poolIndex % clients.Length;
121+
var nextHost = Hosts[nextIndex];
122+
var newClient = InitNewClient(nextHost);
123+
//Don't handle callbacks for new client outside pool
124+
newClient.ClientManager = null;
125+
return newClient;
127126
}
128127

129128
poolIndex++;
@@ -188,21 +187,13 @@ private void InitClient(RedisClient client)
188187

189188
public void DisposeClient(RedisNativeClient client)
190189
{
191-
lock (clients)
190+
for (var i = 0; i < clients.Length; i++)
192191
{
193-
for (var i = 0; i < clients.Length; i++)
194-
{
195-
var writeClient = clients[i];
196-
if (client != writeClient) continue;
197-
client.Active = false;
198-
Monitor.PulseAll(clients);
199-
return;
200-
}
192+
var writeClient = clients[i];
193+
if (client != writeClient) continue;
194+
client.Active = false;
195+
return;
201196
}
202-
203-
//Client not found in any pool, pulse both pools.
204-
lock (clients)
205-
Monitor.PulseAll(clients);
206197
}
207198

208199
/// <summary>
@@ -211,11 +202,7 @@ public void DisposeClient(RedisNativeClient client)
211202
/// <param name="client">The client.</param>
212203
public void DisposeWriteClient(RedisNativeClient client)
213204
{
214-
lock (clients)
215-
{
216-
client.Active = false;
217-
Monitor.PulseAll(clients);
218-
}
205+
client.Active = false;
219206
}
220207

221208
public Dictionary<string, string> GetStats()
@@ -263,14 +250,12 @@ private void AssertValidPool()
263250
public int[] GetClientPoolActiveStates()
264251
{
265252
var activeStates = new int[clients.Length];
266-
lock (clients)
253+
for (int i = 0; i < clients.Length; i++)
267254
{
268-
for (int i = 0; i < clients.Length; i++)
269-
{
270-
activeStates[i] = clients[i] == null
271-
? -1
272-
: clients[i].Active ? 1 : 0;
273-
}
255+
var client = clients[i];
256+
activeStates[i] = client == null
257+
? -1
258+
: client.Active ? 1 : 0;
274259
}
275260
return activeStates;
276261
}

src/ServiceStack.Redis/RedisNativeClient.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,6 +1984,11 @@ public RedisPipelineCommand CreatePipelineCommand()
19841984

19851985
internal bool IsDisposed { get; set; }
19861986

1987+
public bool IsManagedClient
1988+
{
1989+
get { return ClientManager != null; }
1990+
}
1991+
19871992
public void Dispose()
19881993
{
19891994
Dispose(true);

tests/ServiceStack.Redis.Tests/RedisManagerPoolTests.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public void Can_have_different_pool_size_and_host_configurations()
158158
}
159159

160160
[Test]
161-
public void Does_block_ReadWrite_clients_pool()
161+
public void Does_not_block_ReadWrite_clients_pool()
162162
{
163163
using (var manager = new RedisManagerPool(
164164
hosts,
@@ -174,6 +174,11 @@ public void Does_block_ReadWrite_clients_pool()
174174
var client3 = manager.GetClient();
175175
var client4 = manager.GetClient();
176176

177+
Assert.That(((RedisClient)client1).IsManagedClient, Is.True);
178+
Assert.That(((RedisClient)client2).IsManagedClient, Is.True);
179+
Assert.That(((RedisClient)client3).IsManagedClient, Is.True);
180+
Assert.That(((RedisClient)client4).IsManagedClient, Is.True);
181+
177182
Action func = delegate {
178183
Thread.Sleep(delay + TimeSpan.FromSeconds(0.5));
179184
client4.Dispose();
@@ -185,13 +190,15 @@ public void Does_block_ReadWrite_clients_pool()
185190

186191
var client5 = manager.GetClient();
187192

188-
Assert.That(DateTime.Now - start, Is.GreaterThanOrEqualTo(delay));
193+
Assert.That(((RedisClient)client5).IsManagedClient, Is.False); //outside of pool
194+
195+
Assert.That(DateTime.Now - start, Is.LessThan(delay));
189196

190197
AssertClientHasHost(client1, hosts[0]);
191198
AssertClientHasHost(client2, hosts[1]);
192199
AssertClientHasHost(client3, hosts[2]);
193200
AssertClientHasHost(client4, hosts[3]);
194-
AssertClientHasHost(client5, hosts[3]);
201+
AssertClientHasHost(client5, hosts[0]);
195202

196203
mockFactory.VerifyAll();
197204
}

0 commit comments

Comments
 (0)