5
5
import com .google .common .cache .LoadingCache ;
6
6
import com .google .gson .Gson ;
7
7
import com .google .gson .reflect .TypeToken ;
8
- import org .apache .http .util .EntityUtils ;
9
8
import redis .clients .jedis .Jedis ;
9
+ import redis .clients .jedis .JedisPool ;
10
+ import redis .clients .jedis .JedisPoolConfig ;
10
11
import redis .clients .jedis .Transaction ;
11
12
13
+ import java .io .IOException ;
12
14
import java .lang .reflect .Type ;
13
15
import java .net .URI ;
14
16
import java .util .HashMap ;
22
24
*/
23
25
public class RedisFeatureStore implements FeatureStore {
24
26
private static final String DEFAULT_PREFIX = "launchdarkly" ;
25
- private final Jedis jedis ;
27
+ private final JedisPool pool ;
26
28
private LoadingCache <String , FeatureRep <?>> cache ;
27
29
private LoadingCache <String , Boolean > initCache ;
28
30
private String prefix ;
@@ -36,7 +38,7 @@ public class RedisFeatureStore implements FeatureStore {
36
38
* @param cacheTimeSecs an optional timeout for the in-memory cache. If set to 0, no in-memory caching will be performed
37
39
*/
38
40
public RedisFeatureStore (String host , int port , String prefix , long cacheTimeSecs ) {
39
- jedis = new Jedis ( host , port );
41
+ pool = new JedisPool ( getPoolConfig (), host , port );
40
42
setPrefix (prefix );
41
43
createCache (cacheTimeSecs );
42
44
createInitCache (cacheTimeSecs );
@@ -50,7 +52,7 @@ public RedisFeatureStore(String host, int port, String prefix, long cacheTimeSec
50
52
* @param cacheTimeSecs an optional timeout for the in-memory cache. If set to 0, no in-memory caching will be performed
51
53
*/
52
54
public RedisFeatureStore (URI uri , String prefix , long cacheTimeSecs ) {
53
- jedis = new Jedis ( uri );
55
+ pool = new JedisPool ( getPoolConfig (), uri );
54
56
setPrefix (prefix );
55
57
createCache (cacheTimeSecs );
56
58
createInitCache (cacheTimeSecs );
@@ -61,7 +63,7 @@ public RedisFeatureStore(URI uri, String prefix, long cacheTimeSecs) {
61
63
*
62
64
*/
63
65
public RedisFeatureStore () {
64
- jedis = new Jedis ( "localhost" );
66
+ pool = new JedisPool ( getPoolConfig (), "localhost" );
65
67
this .prefix = DEFAULT_PREFIX ;
66
68
}
67
69
@@ -128,18 +130,26 @@ public FeatureRep<?> get(String key) {
128
130
*/
129
131
@ Override
130
132
public Map <String , FeatureRep <?>> all () {
131
- Map <String ,String > featuresJson = jedis .hgetAll (featuresKey ());
132
- Map <String , FeatureRep <?>> result = new HashMap <String , FeatureRep <?>>();
133
- Gson gson = new Gson ();
133
+ Jedis jedis = null ;
134
+ try {
135
+ jedis = getJedis ();
136
+ Map <String ,String > featuresJson = getJedis ().hgetAll (featuresKey ());
137
+ Map <String , FeatureRep <?>> result = new HashMap <String , FeatureRep <?>>();
138
+ Gson gson = new Gson ();
134
139
135
- Type type = new TypeToken <FeatureRep <?>>() {}.getType ();
140
+ Type type = new TypeToken <FeatureRep <?>>() {}.getType ();
136
141
137
- for (Map .Entry <String , String > entry : featuresJson .entrySet ()) {
138
- FeatureRep <?> rep = gson .fromJson (entry .getValue (), type );
139
- result .put (entry .getKey (), rep );
142
+ for (Map .Entry <String , String > entry : featuresJson .entrySet ()) {
143
+ FeatureRep <?> rep = gson .fromJson (entry .getValue (), type );
144
+ result .put (entry .getKey (), rep );
145
+ }
146
+ return result ;
147
+ } finally {
148
+ if (jedis != null ) {
149
+ jedis .close ();
150
+ }
140
151
}
141
152
142
- return result ;
143
153
}
144
154
/**
145
155
* Initializes (or re-initializes) the store with the specified set of features. Any existing entries
@@ -149,16 +159,25 @@ public Map<String, FeatureRep<?>> all() {
149
159
*/
150
160
@ Override
151
161
public void init (Map <String , FeatureRep <?>> features ) {
152
- Gson gson = new Gson ();
153
- Transaction t = jedis .multi ();
162
+ Jedis jedis = null ;
154
163
155
- t .del (featuresKey ());
164
+ try {
165
+ jedis = getJedis ();
166
+ Gson gson = new Gson ();
167
+ Transaction t = jedis .multi ();
156
168
157
- for (FeatureRep <?> f : features .values ()) {
158
- t .hset (featuresKey (), f .key , gson .toJson (f ));
159
- }
169
+ t .del (featuresKey ());
160
170
161
- t .exec ();
171
+ for (FeatureRep <?> f : features .values ()) {
172
+ t .hset (featuresKey (), f .key , gson .toJson (f ));
173
+ }
174
+
175
+ t .exec ();
176
+ } finally {
177
+ if (jedis != null ) {
178
+ jedis .close ();
179
+ }
180
+ }
162
181
}
163
182
164
183
@@ -172,7 +191,9 @@ public void init(Map<String, FeatureRep<?>> features) {
172
191
*/
173
192
@ Override
174
193
public void delete (String key , int version ) {
194
+ Jedis jedis = null ;
175
195
try {
196
+ jedis = getJedis ();
176
197
Gson gson = new Gson ();
177
198
jedis .watch (featuresKey ());
178
199
@@ -192,7 +213,10 @@ public void delete(String key, int version) {
192
213
}
193
214
}
194
215
finally {
195
- jedis .unwatch ();
216
+ if (jedis != null ) {
217
+ jedis .unwatch ();
218
+ jedis .close ();
219
+ }
196
220
}
197
221
198
222
}
@@ -206,7 +230,9 @@ public void delete(String key, int version) {
206
230
*/
207
231
@ Override
208
232
public void upsert (String key , FeatureRep <?> feature ) {
233
+ Jedis jedis = null ;
209
234
try {
235
+ jedis = getJedis ();
210
236
Gson gson = new Gson ();
211
237
jedis .watch (featuresKey ());
212
238
@@ -223,7 +249,10 @@ public void upsert(String key, FeatureRep<?> feature) {
223
249
}
224
250
}
225
251
finally {
226
- jedis .unwatch ();
252
+ if (jedis != null ) {
253
+ jedis .unwatch ();
254
+ jedis .close ();
255
+ }
227
256
}
228
257
}
229
258
@@ -245,26 +274,64 @@ public boolean initialized() {
245
274
return getInit ();
246
275
}
247
276
277
+ /**
278
+ * Releases all resources associated with the store. The store must no longer be used once closed.
279
+ * @throws IOException
280
+ */
281
+ public void close () throws IOException
282
+ {
283
+ pool .destroy ();
284
+ }
285
+
286
+
248
287
249
288
private String featuresKey () {
250
289
return prefix + ":features" ;
251
290
}
252
291
253
292
private Boolean getInit () {
254
- return jedis .exists (featuresKey ());
293
+ Jedis jedis = null ;
294
+
295
+ try {
296
+ jedis = getJedis ();
297
+ return jedis .exists (featuresKey ());
298
+ } finally {
299
+ if (jedis != null ) {
300
+ jedis .close ();
301
+ }
302
+ }
255
303
}
256
304
257
305
private FeatureRep <?> getRedis (String key ) {
258
- Gson gson = new Gson ();
259
- String featureJson = jedis .hget (featuresKey (), key );
306
+ Jedis jedis = null ;
307
+ try {
308
+ jedis = getJedis ();
309
+ Gson gson = new Gson ();
310
+ String featureJson = getJedis ().hget (featuresKey (), key );
311
+
312
+ if (featureJson == null ) {
313
+ return null ;
314
+ }
315
+
316
+ Type type = new TypeToken <FeatureRep <?>>() {}.getType ();
317
+ FeatureRep <?> f = gson .fromJson (featureJson , type );
260
318
261
- if (featureJson == null ) {
262
- return null ;
319
+ return f .deleted ? null : f ;
320
+ } finally {
321
+ if (jedis != null ) {
322
+ jedis .close ();
323
+ }
263
324
}
325
+ }
264
326
265
- Type type = new TypeToken <FeatureRep <?>>() {}.getType ();
266
- FeatureRep <?> f = gson .fromJson (featureJson , type );
327
+ private final Jedis getJedis () {
328
+ return pool .getResource ();
329
+ }
267
330
268
- return f .deleted ? null : f ;
331
+ private final JedisPoolConfig getPoolConfig () {
332
+ JedisPoolConfig config = new JedisPoolConfig ();
333
+ config .setMaxTotal (256 );
334
+ config .setBlockWhenExhausted (false );
335
+ return config ;
269
336
}
270
337
}
0 commit comments