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