1 /*
2  * Hunt - A redis client library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11  
12 module hunt.redis.RedisSlotBasedConnectionHandler;
13 
14 import hunt.redis.RedisClusterConnectionHandler;
15 
16 import hunt.redis.Exceptions;
17 import hunt.redis.HostAndPort;
18 import hunt.redis.Redis;
19 import hunt.redis.RedisPool;
20 import hunt.redis.RedisPoolOptions;
21 
22 import hunt.text.Common;
23 
24 import hunt.collection.List;
25 import hunt.collection.Set;
26 import hunt.util.pool;
27 
28 
29 class RedisSlotBasedConnectionHandler : RedisClusterConnectionHandler {
30 
31   this(HostAndPort[] nodes, RedisPoolOptions poolConfig) {
32     super(nodes, poolConfig);
33   }
34 
35 
36   override
37   Redis getConnection() {
38     // In antirez's redis-rb-cluster implementation,
39     // getRandomConnection always return valid connection (able to
40     // ping-pong)
41     // or exception if all connections are invalid
42 
43     List!(RedisPool) pools = cache.getShuffledNodesPool();
44 
45     foreach(RedisPool pool ; pools) {
46       Redis redis = null;
47       try {
48         redis = pool.borrow();
49 
50         if (redis is null) {
51           continue;
52         }
53 
54         string result = redis.ping();
55 
56         if (result.equalsIgnoreCase("pong")) return redis;
57 
58         redis.close();
59       } catch (RedisException ex) {
60         if (redis !is null) {
61           redis.close();
62         }
63       }
64     }
65 
66     throw new RedisNoReachableClusterNodeException("No reachable node in cluster");
67   }
68 
69   override
70   Redis getConnectionFromSlot(int slot) {
71     RedisPool connectionPool = cache.getSlotPool(slot);
72     if (connectionPool !is null) {
73       // It can't guaranteed to get valid connection because of node
74       // assignment
75       return connectionPool.borrow();
76     } else {
77       renewSlotCache(); //It's abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state
78       connectionPool = cache.getSlotPool(slot);
79       if (connectionPool !is null) {
80         return connectionPool.borrow();
81       } else {
82         //no choice, fallback to new connection to random node
83         return getConnection();
84       }
85     }
86   }
87 }