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.RedisClusterConnectionHandler;
13 
14 import hunt.redis.Exceptions;
15 import hunt.redis.HostAndPort;
16 import hunt.redis.Redis;
17 import hunt.redis.RedisClusterInfoCache;
18 import hunt.redis.RedisPool;
19 import hunt.redis.RedisPoolOptions;
20 
21 import hunt.collection.Map;
22 import hunt.collection.Set;
23 import hunt.logging.ConsoleLogger;
24 import hunt.util.Common;
25 import hunt.util.pool;
26 
27 
28 abstract class RedisClusterConnectionHandler : Closeable {
29     protected RedisClusterInfoCache cache;
30 
31 
32     this(HostAndPort[] nodes, RedisPoolOptions poolConfig) {
33         // this(nodes, poolConfig, connectionTimeout, soTimeout, password, clientName, false, null, null, null, null);
34 
35         this.cache = new RedisClusterInfoCache(poolConfig);
36         initializeSlotsCache(nodes, poolConfig.connectionTimeout, 
37             poolConfig.soTimeout, poolConfig.password, poolConfig.name, poolConfig.ssl);
38     }
39 
40     //   this(Set!(HostAndPort) nodes,
41     //       PoolOptions poolConfig, int connectionTimeout, int soTimeout, string password, string clientName,
42     //       bool ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
43     //       HostnameVerifier hostnameVerifier, RedisClusterHostAndPortMap portMap) {
44     //     this.cache = new RedisClusterInfoCache(poolConfig, connectionTimeout, soTimeout, password, clientName,
45     //         ssl, sslSocketFactory, sslParameters, hostnameVerifier, portMap);
46     //     initializeSlotsCache(nodes, poolConfig, connectionTimeout, soTimeout, password, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
47     //   }
48 
49     abstract Redis getConnection();
50 
51     abstract Redis getConnectionFromSlot(int slot);
52 
53     Redis getConnectionFromNode(HostAndPort node) {
54         return cache.setupNodeIfNotExist(node).borrow();
55     }
56 
57     Map!(string, RedisPool) getNodes() {
58         return cache.getNodes();
59     }
60 
61     //   private void initializeSlotsCache(Set!(HostAndPort) startNodes, PoolOptions poolConfig,
62     //       int connectionTimeout, int soTimeout, string password, string clientName,
63     //       bool ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) 
64 
65     private void initializeSlotsCache(HostAndPort[] startNodes,
66             int connectionTimeout, int soTimeout, string password, string clientName, bool ssl) {
67         foreach (HostAndPort hostAndPort; startNodes) {
68             Redis redis = null;
69             scope(exit) {
70                 if (redis !is null) {
71                     redis.close();
72                 }
73             }
74 
75             try {
76                 // redis = new Redis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout, soTimeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
77                 redis = new Redis(hostAndPort.getHost(), hostAndPort.getPort(),
78                         connectionTimeout, soTimeout, ssl);
79                 if (password !is null) {
80                     redis.auth(password);
81                 }
82                 if (clientName !is null) {
83                     redis.clientSetname(clientName);
84                 }
85                 cache.discoverClusterNodesAndSlots(redis);
86                 break;
87             } catch (RedisConnectionException ex) {
88                 // try next nodes
89                 debug warning(ex.msg);
90                 version(HUNT_REDIS_DEBUG) warning(ex);
91             } catch(Exception ex) {
92                 version(HUNT_REDIS_DEBUG) warning(ex);
93             }
94         }
95     }
96 
97     void renewSlotCache() {
98         cache.renewClusterSlots(null);
99     }
100 
101     void renewSlotCache(Redis redis) {
102         cache.renewClusterSlots(redis);
103     }
104 
105     override void close() {
106         cache.reset();
107     }
108 }