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.RedisPool;
13 
14 import hunt.redis.Redis;
15 import hunt.redis.RedisPoolAbstract;
16 import hunt.redis.RedisPoolConfig;
17 import hunt.redis.RedisFactory;
18 import hunt.redis.Protocol;
19 
20 import hunt.pool.impl.GenericObjectPool;
21 import hunt.pool.impl.GenericObjectPoolConfig;
22 
23 import hunt.redis.Exceptions;
24 import hunt.redis.util.RedisURIHelper;
25 import hunt.net.util.HttpURI;
26 
27 import hunt.logging.ConsoleLogger;
28 
29 /**
30  * 
31  */
32 class RedisPool : RedisPoolAbstract {
33 
34     this() {
35         this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT);
36     }
37 
38     this(RedisPoolConfig config) {
39         this(config, config.host, config.port, config.connectionTimeout,
40             config.soTimeout, config.password, config.database, config.clientName);
41     }
42 
43     this(GenericObjectPoolConfig poolConfig, string host) {
44         this(poolConfig, host, Protocol.DEFAULT_PORT);
45     }
46 
47     this(string host, int port) {
48         this(new GenericObjectPoolConfig(), host, port);
49     }
50 
51     this(string host) {
52         HttpURI uri = new HttpURI(host);
53         if (RedisURIHelper.isValid(uri)) {
54             this.internalPool = new GenericObjectPool!(Redis)(new RedisFactory(uri,
55                     Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null), new GenericObjectPoolConfig());
56         } else {
57             this.internalPool = new GenericObjectPool!(Redis)(new RedisFactory(host,
58                     Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null,
59                     Protocol.DEFAULT_DATABASE, null), new GenericObjectPoolConfig());
60         }
61     }
62 
63     // this(string host, SSLSocketFactory sslSocketFactory,
64     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
65     //   HttpURI uri = HttpURI.create(host);
66     //   if (RedisURIHelper.isValid(uri)) {
67     //     this.internalPool = new GenericObjectPool!(Redis)(new RedisFactory(uri,
68     //         Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null, sslSocketFactory, sslParameters,
69     //         hostnameVerifier), new GenericObjectPoolConfig());
70     //   } else {
71     //     this.internalPool = new GenericObjectPool!(Redis)(new RedisFactory(host,
72     //         Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null,
73     //         Protocol.DEFAULT_DATABASE, null, false, null, null, null), new GenericObjectPoolConfig());
74     //   }
75     // }
76 
77     this(HttpURI uri) {
78         this(new GenericObjectPoolConfig(), uri);
79     }
80 
81     // this(HttpURI uri, SSLSocketFactory sslSocketFactory,
82     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
83     //   this(new GenericObjectPoolConfig(), uri, sslSocketFactory, sslParameters, hostnameVerifier);
84     // }
85 
86     this(HttpURI uri, int timeout) {
87         this(new GenericObjectPoolConfig(), uri, timeout);
88     }
89 
90     // this(HttpURI uri, int timeout, SSLSocketFactory sslSocketFactory,
91     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
92     //   this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters,
93     //       hostnameVerifier);
94     // }
95 
96     this(GenericObjectPoolConfig poolConfig, string host, int port,
97             int timeout, string password) {
98         this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE);
99     }
100 
101     this(GenericObjectPoolConfig poolConfig, string host, int port,
102             int timeout, string password, bool ssl) {
103         this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl);
104     }
105 
106     // this(GenericObjectPoolConfig poolConfig, string host, int port,
107     //     int timeout, string password, bool ssl,
108     //     SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
109     //     HostnameVerifier hostnameVerifier) {
110     //   this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl,
111     //       sslSocketFactory, sslParameters, hostnameVerifier);
112     // }
113 
114     this(GenericObjectPoolConfig poolConfig, string host, int port) {
115         this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT);
116     }
117 
118     this(GenericObjectPoolConfig poolConfig, string host, int port,
119             bool ssl) {
120         this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, ssl);
121     }
122 
123     // this(GenericObjectPoolConfig poolConfig, string host, int port,
124     //     bool ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
125     //     HostnameVerifier hostnameVerifier) {
126     //   this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, ssl, sslSocketFactory, sslParameters,
127     //       hostnameVerifier);
128     // }
129 
130     this(GenericObjectPoolConfig poolConfig, string host, int port,
131             int timeout) {
132         this(poolConfig, host, port, timeout, null);
133     }
134 
135     this(GenericObjectPoolConfig poolConfig, string host, int port,
136             int timeout, bool ssl) {
137         this(poolConfig, host, port, timeout, null, ssl);
138     }
139 
140     // this(GenericObjectPoolConfig poolConfig, string host, int port,
141     //     int timeout, bool ssl, SSLSocketFactory sslSocketFactory,
142     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
143     //   this(poolConfig, host, port, timeout, null, ssl, sslSocketFactory, sslParameters,
144     //       hostnameVerifier);
145     // }
146 
147     this(GenericObjectPoolConfig poolConfig, string host, int port,
148             int timeout, string password, int database) {
149         this(poolConfig, host, port, timeout, password, database, null);
150     }
151 
152     this(GenericObjectPoolConfig poolConfig, string host, int port,
153             int timeout, string password, int database, bool ssl) {
154         this(poolConfig, host, port, timeout, password, database, null, ssl);
155     }
156 
157     // this(GenericObjectPoolConfig poolConfig, string host, int port,
158     //     int timeout, string password, int database, bool ssl,
159     //     SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
160     //     HostnameVerifier hostnameVerifier) {
161     //   this(poolConfig, host, port, timeout, password, database, null, ssl, sslSocketFactory,
162     //       sslParameters, hostnameVerifier);
163     // }
164 
165     this(GenericObjectPoolConfig poolConfig, string host, int port,
166             int timeout, string password, int database, string clientName) {
167         this(poolConfig, host, port, timeout, timeout, password, database, clientName);
168     }
169 
170     this(GenericObjectPoolConfig poolConfig, string host, int port,
171             int timeout, string password, int database, string clientName,
172             bool ssl) {
173         this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl);
174     }
175 
176     // this(GenericObjectPoolConfig poolConfig, string host, int port,
177     //     int timeout, string password, int database, string clientName,
178     //     bool ssl, SSLSocketFactory sslSocketFactory,
179     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
180     //   this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl,
181     //       sslSocketFactory, sslParameters, hostnameVerifier);
182     // }
183 
184     // this(GenericObjectPoolConfig poolConfig, string host, int port,
185     //     int connectionTimeout, int soTimeout, string password, int database,
186     //     string clientName, bool ssl, SSLSocketFactory sslSocketFactory,
187     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
188     //   super(poolConfig, new RedisFactory(host, port, connectionTimeout, soTimeout, password,
189     //       database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier));
190     // }
191 
192     this(GenericObjectPoolConfig poolConfig) {
193         this(poolConfig, Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT);
194     }
195 
196     this(string host, int port, bool ssl) {
197         this(new GenericObjectPoolConfig(), host, port, ssl);
198     }
199 
200     this(GenericObjectPoolConfig poolConfig, string host, int port,
201             int connectionTimeout, int soTimeout, string password, int database,
202             string clientName) {
203         super(poolConfig, new RedisFactory(host, port, connectionTimeout, soTimeout, password,
204                 database, clientName));
205     }
206 
207     // this(string host, int port, bool ssl,
208     //     SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
209     //     HostnameVerifier hostnameVerifier) {
210     //   this(new GenericObjectPoolConfig(), host, port, ssl, sslSocketFactory, sslParameters,
211     //       hostnameVerifier);
212     // }
213 
214     this(GenericObjectPoolConfig poolConfig, string host, int port,
215             int connectionTimeout, int soTimeout, string password, int database,
216             string clientName, bool ssl) {
217         // this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName, ssl,
218         //     null, null, null);
219         this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName);    
220     }
221 
222     this(GenericObjectPoolConfig poolConfig, HttpURI uri) {
223         this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT);
224     }
225 
226     // this(GenericObjectPoolConfig poolConfig, HttpURI uri,
227     //     SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
228     //     HostnameVerifier hostnameVerifier) {
229     //   this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT, sslSocketFactory, sslParameters,
230     //       hostnameVerifier);
231     // }
232 
233     this(GenericObjectPoolConfig poolConfig, HttpURI uri, int timeout) {
234         this(poolConfig, uri, timeout, timeout);
235     }
236 
237     // this(GenericObjectPoolConfig poolConfig, HttpURI uri, int timeout,
238     //     SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
239     //     HostnameVerifier hostnameVerifier) {
240     //   this(poolConfig, uri, timeout, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
241     // }
242 
243     this(GenericObjectPoolConfig poolConfig, HttpURI uri,
244             int connectionTimeout, int soTimeout) {
245         super(poolConfig, new RedisFactory(uri, connectionTimeout, soTimeout, null));
246     }
247 
248     // this(GenericObjectPoolConfig poolConfig, HttpURI uri,
249     //     int connectionTimeout, int soTimeout, SSLSocketFactory sslSocketFactory,
250     //     SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
251     //   super(poolConfig, new RedisFactory(uri, connectionTimeout, soTimeout, null, sslSocketFactory,
252     //       sslParameters, hostnameVerifier));
253     // }
254 
255     void initPool(RedisPoolConfig config) {
256         RedisFactory redisFactory = new RedisFactory(config.host, config.port, config.connectionTimeout,
257             config.soTimeout, config.password, config.database, config.clientName);
258         initPool(config, redisFactory);
259     }
260 
261     alias initPool = RedisPoolAbstract.initPool;
262 
263     override
264     Redis getResource() {
265         Redis redis = super.getResource();
266         redis.setDataSource(this);
267         return redis;
268     }
269 
270     override
271     protected void returnBrokenResource(Redis resource) {
272         if (resource !is null) {
273             returnBrokenResourceObject(resource);
274         }
275     }
276 
277     override
278     protected void returnResource(Redis resource) {
279         if (resource !is null) {
280             try {
281                 resource.resetState();
282                 returnResourceObject(resource);
283             } catch (Exception e) {
284                 returnBrokenResource(resource);
285                 throw new RedisException("Resource is returned to the pool as broken", e);
286             }
287         }
288     }
289 }
290 
291 
292 
293 @property RedisPool defaultRedisPool() @trusted {
294     import std.concurrency : initOnce;
295 
296     __gshared RedisPool pool;
297     return initOnce!pool({
298         auto config = defalutPoolConfig();
299         auto p = new RedisPool(config, config.host, config.port, config.connectionTimeout,
300             config.soTimeout, config.password, config.database, config.clientName);
301         return p;
302     }());
303 }
304 
305 private __gshared RedisPoolConfig _defalutPoolConfig;
306 
307 RedisPoolConfig defalutPoolConfig() {
308     if(_defalutPoolConfig is null) {
309         _defalutPoolConfig = new RedisPoolConfig();
310     }
311     return _defalutPoolConfig;
312 }
313 
314 
315 void defalutPoolConfig(RedisPoolConfig config) {
316     _defalutPoolConfig = config;
317 }