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.BinaryShardedRedis;
13 
14 import hunt.redis.Client;
15 import hunt.redis.Exceptions;
16 import hunt.redis.GeoCoordinate;
17 import hunt.redis.GeoRadiusResponse;
18 import hunt.redis.GeoUnit;
19 import hunt.redis.ListPosition;
20 import hunt.redis.Redis;
21 import hunt.redis.RedisShardInfo;
22 import hunt.redis.ShardedRedisPipeline;
23 import hunt.redis.ScanParams;
24 import hunt.redis.ScanResult;
25 import hunt.redis.SortingParams;
26 import hunt.redis.Tuple;
27 
28 
29 import hunt.collection.Collection;
30 import hunt.collection.List;
31 import hunt.collection.Map;
32 import hunt.collection.Set;
33 
34 import hunt.redis.commands.BinaryRedisCommands;
35 import hunt.redis.Protocol;
36 import hunt.redis.params.GeoRadiusParam;
37 import hunt.redis.params.SetParams;
38 import hunt.redis.params.ZAddParams;
39 import hunt.redis.params.ZIncrByParams;
40 import hunt.redis.util.Hashing;
41 import hunt.redis.util.Sharded;
42 
43 import hunt.Double;
44 import hunt.Long;
45 
46 import std.conv;
47 import std.regex;
48 alias Pattern = Regex!char;
49 
50 /**
51  * 
52  */
53 class BinaryShardedRedis : Sharded!(Redis, RedisShardInfo), BinaryRedisCommands {
54     this(List!(RedisShardInfo) shards) {
55         super(shards);
56     }
57 
58     this(List!(RedisShardInfo) shards, Hashing algo) {
59         super(shards, algo);
60     }
61 
62     this(List!(RedisShardInfo) shards, Pattern keyTagPattern) {
63         super(shards, keyTagPattern);
64     }
65 
66     this(List!(RedisShardInfo) shards, Hashing algo, Pattern keyTagPattern) {
67         super(shards, algo, keyTagPattern);
68     }
69 
70     void disconnect() {
71         foreach(Redis jedis ; getAllShards()) {
72             if (jedis.isConnected()) {
73                 try {
74                     jedis.quit();
75                 } catch (RedisConnectionException e) {
76                     import hunt.logging.ConsoleLogger;
77                     warning(e);
78                     // ignore the exception node, so that all other normal nodes can release all connections.
79                 }
80                 // try {
81                 //     jedis.disconnect();
82                 // } catch (RedisConnectionException e) {
83                 //     // ignore the exception node, so that all other normal nodes can release all connections.
84                 // }
85             }
86         }
87     }
88 
89     protected Redis create(RedisShardInfo shard) {
90         return new Redis(shard);
91     }
92 
93     override
94     string set(const(ubyte)[] key, const(ubyte)[] value) {
95         Redis j = getShard(key);
96         return j.set(key, value);
97     }
98 
99     override
100     string set(const(ubyte)[] key, const(ubyte)[] value, SetParams params) {
101         Redis j = getShard(key);
102         return j.set(key, value, params);
103     }
104 
105     override
106     const(ubyte)[] get(const(ubyte)[] key) {
107         Redis j = getShard(key);
108         return j.get(key);
109     }
110 
111     override
112     bool exists(const(ubyte)[] key) {
113         Redis j = getShard(key);
114         return j.exists(key);
115     }
116 
117     override
118     string type(const(ubyte)[] key) {
119         Redis j = getShard(key);
120         return j.type(key);
121     }
122 
123     override
124     const(ubyte)[] dump(const(ubyte)[] key) {
125         Redis j = getShard(key);
126         return j.dump(key);
127     }
128 
129     override
130     string restore(const(ubyte)[] key, int ttl, const(ubyte)[] serializedValue) {
131         Redis j = getShard(key);
132         return j.restore(key, ttl, serializedValue);
133     }
134 
135     override
136     string restoreReplace(const(ubyte)[] key, int ttl, const(ubyte)[] serializedValue) {
137         Redis j = getShard(key);
138         return j.restoreReplace(key, ttl, serializedValue);
139     }
140 
141     override
142     Long expire(const(ubyte)[] key, int seconds) {
143         Redis j = getShard(key);
144         return j.expire(key, seconds);
145     }
146 
147     override
148     Long pexpire(const(ubyte)[] key, long milliseconds) {
149         Redis j = getShard(key);
150         return j.pexpire(key, milliseconds);
151     }
152 
153     override
154     Long expireAt(const(ubyte)[] key, long unixTime) {
155         Redis j = getShard(key);
156         return j.expireAt(key, unixTime);
157     }
158 
159     override
160     Long pexpireAt(const(ubyte)[] key, long millisecondsTimestamp) {
161         Redis j = getShard(key);
162         return j.pexpireAt(key, millisecondsTimestamp);
163     }
164 
165     override
166     Long ttl(const(ubyte)[] key) {
167         Redis j = getShard(key);
168         return j.ttl(key);
169     }
170 
171     override
172     Long pttl(const(ubyte)[] key) {
173         Redis j = getShard(key);
174         return j.pttl(key);
175     }
176 
177     override
178     Long touch(const(ubyte)[] key) {
179         Redis j = getShard(key);
180         return j.touch(key);
181     }
182 
183     override
184     const(ubyte)[] getSet(const(ubyte)[] key, const(ubyte)[] value) {
185         Redis j = getShard(key);
186         return j.getSet(key, value);
187     }
188 
189     override
190     Long setnx(const(ubyte)[] key, const(ubyte)[] value) {
191         Redis j = getShard(key);
192         return j.setnx(key, value);
193     }
194 
195     override
196     string setex(const(ubyte)[] key, int seconds, const(ubyte)[] value) {
197         Redis j = getShard(key);
198         return j.setex(key, seconds, value);
199     }
200 
201     override
202     string psetex(const(ubyte)[] key, long milliseconds, const(ubyte)[] value) {
203         Redis j = getShard(key);
204         return j.psetex(key, milliseconds, value);
205     }
206 
207     override
208     Long decrBy(const(ubyte)[] key, long decrement) {
209         Redis j = getShard(key);
210         return j.decrBy(key, decrement);
211     }
212 
213     override
214     Long decr(const(ubyte)[] key) {
215         Redis j = getShard(key);
216         return j.decr(key);
217     }
218 
219     override
220     Long del(const(ubyte)[] key) {
221         Redis j = getShard(key);
222         return j.del(key);
223     }
224 
225     override
226     Long unlink(const(ubyte)[] key) {
227         Redis j = getShard(key);
228         return j.unlink(key);
229     }
230 
231     override
232     Long incrBy(const(ubyte)[] key, long increment) {
233         Redis j = getShard(key);
234         return j.incrBy(key, increment);
235     }
236 
237     override
238     Double incrByFloat(const(ubyte)[] key, double increment) {
239         Redis j = getShard(key);
240         return j.incrByFloat(key, increment);
241     }
242 
243 //     override
244 //     Long incr(const(ubyte)[] key) {
245 //         Redis j = getShard(key);
246 //         return j.incr(key);
247 //     }
248 
249 //     override
250 //     Long append(const(ubyte)[] key, const(ubyte)[] value) {
251 //         Redis j = getShard(key);
252 //         return j.append(key, value);
253 //     }
254 
255 //     override
256 //     const(ubyte)[] substr(const(ubyte)[] key, int start, int end) {
257 //         Redis j = getShard(key);
258 //         return j.substr(key, start, end);
259 //     }
260 
261 //     override
262 //     Long hset(const(ubyte)[] key, const(ubyte)[] field, const(ubyte)[] value) {
263 //         Redis j = getShard(key);
264 //         return j.hset(key, field, value);
265 //     }
266 
267 //     override
268 //     Long hset(const(ubyte)[] key, Map!(const(ubyte)[], const(ubyte)[]) hash) {
269 //         Redis j = getShard(key);
270 //         return j.hset(key, hash);
271 //     }
272 
273 //     override
274 //     const(ubyte)[] hget(const(ubyte)[] key, const(ubyte)[] field) {
275 //         Redis j = getShard(key);
276 //         return j.hget(key, field);
277 //     }
278 
279 //     override
280 //     Long hsetnx(const(ubyte)[] key, const(ubyte)[] field, const(ubyte)[] value) {
281 //         Redis j = getShard(key);
282 //         return j.hsetnx(key, field, value);
283 //     }
284 
285 //     override
286 //     string hmset(const(ubyte)[] key, Map!(const(ubyte)[], const(ubyte)[]) hash) {
287 //         Redis j = getShard(key);
288 //         return j.hmset(key, hash);
289 //     }
290 
291 //     override
292 //     List!(const(ubyte)[]) hmget(const(ubyte)[] key, const(ubyte)[][] fields...) {
293 //         Redis j = getShard(key);
294 //         return j.hmget(key, fields);
295 //     }
296 
297 //     override
298 //     Long hincrBy(const(ubyte)[] key, const(ubyte)[] field, long value) {
299 //         Redis j = getShard(key);
300 //         return j.hincrBy(key, field, value);
301 //     }
302 
303 //     override
304 //     Double hincrByFloat(const(ubyte)[] key, const(ubyte)[] field, double value) {
305 //         Redis j = getShard(key);
306 //         return j.hincrByFloat(key, field, value);
307 //     }
308 
309 //     override
310 //     bool hexists(const(ubyte)[] key, const(ubyte)[] field) {
311 //         Redis j = getShard(key);
312 //         return j.hexists(key, field);
313 //     }
314 
315 //     override
316 //     Long hdel(const(ubyte)[] key, const(ubyte)[][] fields...) {
317 //         Redis j = getShard(key);
318 //         return j.hdel(key, fields);
319 //     }
320 
321 //     override
322 //     Long hlen(const(ubyte)[] key) {
323 //         Redis j = getShard(key);
324 //         return j.hlen(key);
325 //     }
326 
327 //     override
328 //     Set!(const(ubyte)[]) hkeys(const(ubyte)[] key) {
329 //         Redis j = getShard(key);
330 //         return j.hkeys(key);
331 //     }
332 
333 //     override
334 //     Collection!(const(ubyte)[]) hvals(const(ubyte)[] key) {
335 //         Redis j = getShard(key);
336 //         return j.hvals(key);
337 //     }
338 
339 //     override
340 //     Map!(const(ubyte)[], const(ubyte)[]) hgetAll(const(ubyte)[] key) {
341 //         Redis j = getShard(key);
342 //         return j.hgetAll(key);
343 //     }
344 
345 //     override
346 //     Long rpush(const(ubyte)[] key, const(ubyte)[][] strings...) {
347 //         Redis j = getShard(key);
348 //         return j.rpush(key, strings);
349 //     }
350 
351 //     override
352 //     Long lpush(const(ubyte)[] key, const(ubyte)[][] strings...) {
353 //         Redis j = getShard(key);
354 //         return j.lpush(key, strings);
355 //     }
356 
357     override
358     Long strlen(const(ubyte)[] key) {
359         Redis j = getShard(key);
360         return j.strlen(key);
361     }
362 
363 //     override
364 //     Long lpushx(const(ubyte)[] key, const(ubyte)[][] string...) {
365 //         Redis j = getShard(key);
366 //         return j.lpushx(key, string);
367 //     }
368 
369     override
370     Long persist(const(ubyte)[] key) {
371         Redis j = getShard(key);
372         return j.persist(key);
373     }
374 
375 //     override
376 //     Long rpushx(const(ubyte)[] key, const(ubyte)[][] string...) {
377 //         Redis j = getShard(key);
378 //         return j.rpushx(key, string);
379 //     }
380 
381 //     override
382 //     Long llen(const(ubyte)[] key) {
383 //         Redis j = getShard(key);
384 //         return j.llen(key);
385 //     }
386 
387 //     override
388 //     List!(const(ubyte)[]) lrange(const(ubyte)[] key, long start, long stop) {
389 //         Redis j = getShard(key);
390 //         return j.lrange(key, start, stop);
391 //     }
392 
393 //     override
394 //     string ltrim(const(ubyte)[] key, long start, long stop) {
395 //         Redis j = getShard(key);
396 //         return j.ltrim(key, start, stop);
397 //     }
398 
399 //     override
400 //     const(ubyte)[] lindex(const(ubyte)[] key, long index) {
401 //         Redis j = getShard(key);
402 //         return j.lindex(key, index);
403 //     }
404 
405 //     override
406 //     string lset(const(ubyte)[] key, long index, const(ubyte)[] value) {
407 //         Redis j = getShard(key);
408 //         return j.lset(key, index, value);
409 //     }
410 
411 //     override
412 //     Long lrem(const(ubyte)[] key, long count, const(ubyte)[] value) {
413 //         Redis j = getShard(key);
414 //         return j.lrem(key, count, value);
415 //     }
416 
417 //     override
418 //     const(ubyte)[] lpop(const(ubyte)[] key) {
419 //         Redis j = getShard(key);
420 //         return j.lpop(key);
421 //     }
422 
423 //     override
424 //     const(ubyte)[] rpop(const(ubyte)[] key) {
425 //         Redis j = getShard(key);
426 //         return j.rpop(key);
427 //     }
428 
429 //     override
430 //     Long sadd(const(ubyte)[] key, const(ubyte)[][] members...) {
431 //         Redis j = getShard(key);
432 //         return j.sadd(key, members);
433 //     }
434 
435 //     override
436 //     Set!(const(ubyte)[]) smembers(const(ubyte)[] key) {
437 //         Redis j = getShard(key);
438 //         return j.smembers(key);
439 //     }
440 
441 //     override
442 //     Long srem(const(ubyte)[] key, const(ubyte)[][] members...) {
443 //         Redis j = getShard(key);
444 //         return j.srem(key, members);
445 //     }
446 
447 //     override
448 //     const(ubyte)[] spop(const(ubyte)[] key) {
449 //         Redis j = getShard(key);
450 //         return j.spop(key);
451 //     }
452 
453 //     override
454 //     Set!(const(ubyte)[]) spop(const(ubyte)[] key, long count) {
455 //         Redis j = getShard(key);
456 //         return j.spop(key, count);
457 //     }
458 
459 //     override
460 //     Long scard(const(ubyte)[] key) {
461 //         Redis j = getShard(key);
462 //         return j.scard(key);
463 //     }
464 
465 //     override
466 //     bool sismember(const(ubyte)[] key, const(ubyte)[] member) {
467 //         Redis j = getShard(key);
468 //         return j.sismember(key, member);
469 //     }
470 
471 //     override
472 //     const(ubyte)[] srandmember(const(ubyte)[] key) {
473 //         Redis j = getShard(key);
474 //         return j.srandmember(key);
475 //     }
476 
477 //     override
478 //     List!(const(ubyte)[]) srandmember(const(ubyte)[] key, int count) {
479 //         Redis j = getShard(key);
480 //         return j.srandmember(key, count);
481 //     }
482 
483 //     override
484 //     Long zadd(const(ubyte)[] key, double score, const(ubyte)[] member) {
485 //         Redis j = getShard(key);
486 //         return j.zadd(key, score, member);
487 //     }
488 
489 //     override
490 //     Long zadd(const(ubyte)[] key, double score, const(ubyte)[] member, ZAddParams params) {
491 //         Redis j = getShard(key);
492 //         return j.zadd(key, score, member, params);
493 //     }
494 
495 //     override
496 //     Long zadd(const(ubyte)[] key, Map!(const(ubyte)[], Double) scoreMembers) {
497 //         Redis j = getShard(key);
498 //         return j.zadd(key, scoreMembers);
499 //     }
500 
501 //     override
502 //     Long zadd(const(ubyte)[] key, Map!(const(ubyte)[], Double) scoreMembers, ZAddParams params) {
503 //         Redis j = getShard(key);
504 //         return j.zadd(key, scoreMembers, params);
505 //     }
506 
507 //     override
508 //     Set!(const(ubyte)[]) zrange(const(ubyte)[] key, long start, long stop) {
509 //         Redis j = getShard(key);
510 //         return j.zrange(key, start, stop);
511 //     }
512 
513 //     override
514 //     Long zrem(const(ubyte)[] key, const(ubyte)[][] members...) {
515 //         Redis j = getShard(key);
516 //         return j.zrem(key, members);
517 //     }
518 
519 //     override
520 //     Double zincrby(const(ubyte)[] key, double increment, const(ubyte)[] member) {
521 //         Redis j = getShard(key);
522 //         return j.zincrby(key, increment, member);
523 //     }
524 
525 //     override
526 //     Double zincrby(const(ubyte)[] key, double increment, const(ubyte)[] member, ZIncrByParams params) {
527 //         Redis j = getShard(key);
528 //         return j.zincrby(key, increment, member, params);
529 //     }
530 
531 //     override
532 //     Long zrank(const(ubyte)[] key, const(ubyte)[] member) {
533 //         Redis j = getShard(key);
534 //         return j.zrank(key, member);
535 //     }
536 
537 //     override
538 //     Long zrevrank(const(ubyte)[] key, const(ubyte)[] member) {
539 //         Redis j = getShard(key);
540 //         return j.zrevrank(key, member);
541 //     }
542 
543 //     override
544 //     Set!(const(ubyte)[]) zrevrange(const(ubyte)[] key, long start, long stop) {
545 //         Redis j = getShard(key);
546 //         return j.zrevrange(key, start, stop);
547 //     }
548 
549 //     override
550 //     Set!(Tuple) zrangeWithScores(const(ubyte)[] key, long start, long stop) {
551 //         Redis j = getShard(key);
552 //         return j.zrangeWithScores(key, start, stop);
553 //     }
554 
555 //     override
556 //     Set!(Tuple) zrevrangeWithScores(const(ubyte)[] key, long start, long stop) {
557 //         Redis j = getShard(key);
558 //         return j.zrevrangeWithScores(key, start, stop);
559 //     }
560 
561 //     override
562 //     Long zcard(const(ubyte)[] key) {
563 //         Redis j = getShard(key);
564 //         return j.zcard(key);
565 //     }
566 
567 //     override
568 //     Double zscore(const(ubyte)[] key, const(ubyte)[] member) {
569 //         Redis j = getShard(key);
570 //         return j.zscore(key, member);
571 //     }
572 
573 //     override
574 //     List!(const(ubyte)[]) sort(const(ubyte)[] key) {
575 //         Redis j = getShard(key);
576 //         return j.sort(key);
577 //     }
578 
579 //     override
580 //     List!(const(ubyte)[]) sort(const(ubyte)[] key, SortingParams sortingParameters) {
581 //         Redis j = getShard(key);
582 //         return j.sort(key, sortingParameters);
583 //     }
584 
585 //     override
586 //     Long zcount(const(ubyte)[] key, double min, double max) {
587 //         Redis j = getShard(key);
588 //         return j.zcount(key, min, max);
589 //     }
590 
591 //     override
592 //     Long zcount(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
593 //         Redis j = getShard(key);
594 //         return j.zcount(key, min, max);
595 //     }
596 
597 //     override
598 //     Set!(const(ubyte)[]) zrangeByScore(const(ubyte)[] key, double min, double max) {
599 //         Redis j = getShard(key);
600 //         return j.zrangeByScore(key, min, max);
601 //     }
602 
603 //     override
604 //     Set!(const(ubyte)[]) zrangeByScore(const(ubyte)[] key, double min, double max, int offset, int count) {
605 //         Redis j = getShard(key);
606 //         return j.zrangeByScore(key, min, max, offset, count);
607 //     }
608 
609 //     override
610 //     Set!(Tuple) zrangeByScoreWithScores(const(ubyte)[] key, double min, double max) {
611 //         Redis j = getShard(key);
612 //         return j.zrangeByScoreWithScores(key, min, max);
613 //     }
614 
615 //     override
616 //     Set!(Tuple) zrangeByScoreWithScores(const(ubyte)[] key, double min, double max, int offset,
617 //             int count) {
618 //         Redis j = getShard(key);
619 //         return j.zrangeByScoreWithScores(key, min, max, offset, count);
620 //     }
621 
622 //     override
623 //     Set!(const(ubyte)[]) zrangeByScore(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
624 //         Redis j = getShard(key);
625 //         return j.zrangeByScore(key, min, max);
626 //     }
627 
628 //     override
629 //     Set!(Tuple) zrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
630 //         Redis j = getShard(key);
631 //         return j.zrangeByScoreWithScores(key, min, max);
632 //     }
633 
634 //     override
635 //     Set!(Tuple) zrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max, int offset,
636 //             int count) {
637 //         Redis j = getShard(key);
638 //         return j.zrangeByScoreWithScores(key, min, max, offset, count);
639 //     }
640 
641 //     override
642 //     Set!(const(ubyte)[]) zrangeByScore(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max, int offset, int count) {
643 //         Redis j = getShard(key);
644 //         return j.zrangeByScore(key, min, max, offset, count);
645 //     }
646 
647 //     override
648 //     Set!(const(ubyte)[]) zrevrangeByScore(const(ubyte)[] key, double max, double min) {
649 //         Redis j = getShard(key);
650 //         return j.zrevrangeByScore(key, max, min);
651 //     }
652 
653 //     override
654 //     Set!(const(ubyte)[]) zrevrangeByScore(const(ubyte)[] key, double max, double min, int offset, int count) {
655 //         Redis j = getShard(key);
656 //         return j.zrevrangeByScore(key, max, min, offset, count);
657 //     }
658 
659 //     override
660 //     Set!(Tuple) zrevrangeByScoreWithScores(const(ubyte)[] key, double max, double min) {
661 //         Redis j = getShard(key);
662 //         return j.zrevrangeByScoreWithScores(key, max, min);
663 //     }
664 
665 //     override
666 //     Set!(Tuple) zrevrangeByScoreWithScores(const(ubyte)[] key, double max, double min, int offset,
667 //             int count) {
668 //         Redis j = getShard(key);
669 //         return j.zrevrangeByScoreWithScores(key, max, min, offset, count);
670 //     }
671 
672 //     override
673 //     Set!(const(ubyte)[]) zrevrangeByScore(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min) {
674 //         Redis j = getShard(key);
675 //         return j.zrevrangeByScore(key, max, min);
676 //     }
677 
678 //     override
679 //     Set!(const(ubyte)[]) zrevrangeByScore(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min, int offset, int count) {
680 //         Redis j = getShard(key);
681 //         return j.zrevrangeByScore(key, max, min, offset, count);
682 //     }
683 
684 //     override
685 //     Set!(Tuple) zrevrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min) {
686 //         Redis j = getShard(key);
687 //         return j.zrevrangeByScoreWithScores(key, max, min);
688 //     }
689 
690 //     override
691 //     Set!(Tuple) zrevrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min, int offset,
692 //             int count) {
693 //         Redis j = getShard(key);
694 //         return j.zrevrangeByScoreWithScores(key, max, min, offset, count);
695 //     }
696 
697 //     override
698 //     Long zremrangeByRank(const(ubyte)[] key, long start, long stop) {
699 //         Redis j = getShard(key);
700 //         return j.zremrangeByRank(key, start, stop);
701 //     }
702 
703 //     override
704 //     Long zremrangeByScore(const(ubyte)[] key, double min, double max) {
705 //         Redis j = getShard(key);
706 //         return j.zremrangeByScore(key, min, max);
707 //     }
708 
709 //     override
710 //     Long zremrangeByScore(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
711 //         Redis j = getShard(key);
712 //         return j.zremrangeByScore(key, min, max);
713 //     }
714 
715 //     override
716 //     Long zlexcount(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
717 //         Redis j = getShard(key);
718 //         return j.zlexcount(key, min, max);
719 //     }
720 
721 //     override
722 //     Set!(const(ubyte)[]) zrangeByLex(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
723 //         Redis j = getShard(key);
724 //         return j.zrangeByLex(key, min, max);
725 //     }
726 
727 //     override
728 //     Set!(const(ubyte)[]) zrangeByLex(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max,
729 //             int offset, int count) {
730 //         Redis j = getShard(key);
731 //         return j.zrangeByLex(key, min, max, offset, count);
732 //     }
733 
734 //     override
735 //     Set!(const(ubyte)[]) zrevrangeByLex(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min) {
736 //         Redis j = getShard(key);
737 //         return j.zrevrangeByLex(key, max, min);
738 //     }
739 
740 //     override
741 //     Set!(const(ubyte)[]) zrevrangeByLex(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min, int offset, int count) {
742 //         Redis j = getShard(key);
743 //         return j.zrevrangeByLex(key, max, min, offset, count);
744 //     }
745 
746 //     override
747 //     Long zremrangeByLex(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
748 //         Redis j = getShard(key);
749 //         return j.zremrangeByLex(key, min, max);
750 //     }
751 
752 //     override
753 //     Long linsert(const(ubyte)[] key, ListPosition where, const(ubyte)[] pivot, const(ubyte)[] value) {
754 //         Redis j = getShard(key);
755 //         return j.linsert(key, where, pivot, value);
756 //     }
757 
758 //     ShardedRedisPipeline pipelined() {
759 //         ShardedRedisPipeline pipeline = new ShardedRedisPipeline();
760 //         pipeline.setShardedRedis(this);
761 //         return pipeline;
762 //     }
763 
764 //     Long objectRefcount(const(ubyte)[] key) {
765 //         Redis j = getShard(key);
766 //         return j.objectRefcount(key);
767 //     }
768 
769 //     const(ubyte)[] objectEncoding(const(ubyte)[] key) {
770 //         Redis j = getShard(key);
771 //         return j.objectEncoding(key);
772 //     }
773 
774 //     Long objectIdletime(const(ubyte)[] key) {
775 //         Redis j = getShard(key);
776 //         return j.objectIdletime(key);
777 //     }
778 
779     override
780     bool setbit(const(ubyte)[] key, long offset, bool value) {
781         Redis j = getShard(key);
782         return j.setbit(key, offset, value);
783     }
784 
785     override
786     bool setbit(const(ubyte)[] key, long offset, const(ubyte)[] value) {
787         Redis j = getShard(key);
788         return j.setbit(key, offset, value);
789     }
790 
791     override
792     bool getbit(const(ubyte)[] key, long offset) {
793         Redis j = getShard(key);
794         return j.getbit(key, offset);
795     }
796 
797     override
798     Long setrange(const(ubyte)[] key, long offset, const(ubyte)[] value) {
799         Redis j = getShard(key);
800         return j.setrange(key, offset, value);
801     }
802 
803     override
804     const(ubyte)[] getrange(const(ubyte)[] key, long startOffset, long endOffset) {
805         Redis j = getShard(key);
806         return j.getrange(key, startOffset, endOffset);
807     }
808 
809     override
810     Long move(const(ubyte)[] key, int dbIndex) {
811         Redis j = getShard(key);
812         return j.move(key, dbIndex);
813     }
814 
815     override
816     const(ubyte)[] echo(const(ubyte)[] arg) {
817         Redis j = getShard(arg);
818         return j.echo(arg);
819     }
820 
821 //     List!(const(ubyte)[]) brpop(const(ubyte)[] arg) {
822 //         Redis j = getShard(arg);
823 //         return j.brpop(arg);
824 //     }
825 
826 //     List!(const(ubyte)[]) blpop(const(ubyte)[] arg) {
827 //         Redis j = getShard(arg);
828 //         return j.blpop(arg);
829 //     }
830 
831     override
832     Long bitcount(const(ubyte)[] key) {
833         Redis j = getShard(key);
834         return j.bitcount(key);
835     }
836 
837     override
838     Long bitcount(const(ubyte)[] key, long start, long end) {
839         Redis j = getShard(key);
840         return j.bitcount(key, start, end);
841     }
842 
843     override
844     Long pfadd(const(ubyte)[] key, const(ubyte)[][] elements...) {
845         Redis j = getShard(key);
846         return j.pfadd(key, elements);
847     }
848 
849     override
850     Long pfcount(const(ubyte)[] key) {
851         Redis j = getShard(key);
852         return j.pfcount(key);
853     }
854 
855 //     override
856 //     Long geoadd(const(ubyte)[] key, double longitude, double latitude, const(ubyte)[] member) {
857 //         Redis j = getShard(key);
858 //         return j.geoadd(key, longitude, latitude, member);
859 //     }
860 
861 //     override
862 //     Long geoadd(const(ubyte)[] key, Map!(const(ubyte)[], GeoCoordinate) memberCoordinateMap) {
863 //         Redis j = getShard(key);
864 //         return j.geoadd(key, memberCoordinateMap);
865 //     }
866 
867 //     override
868 //     Double geodist(const(ubyte)[] key, const(ubyte)[] member1, const(ubyte)[] member2) {
869 //         Redis j = getShard(key);
870 //         return j.geodist(key, member1, member2);
871 //     }
872 
873 //     override
874 //     Double geodist(const(ubyte)[] key, const(ubyte)[] member1, const(ubyte)[] member2, GeoUnit unit) {
875 //         Redis j = getShard(key);
876 //         return j.geodist(key, member1, member2, unit);
877 //     }
878 
879 //     override
880 //     List!(const(ubyte)[]) geohash(const(ubyte)[] key, const(ubyte)[][] members...) {
881 //         Redis j = getShard(key);
882 //         return j.geohash(key, members);
883 //     }
884 
885 //     override
886 //     List!(GeoCoordinate) geopos(const(ubyte)[] key, const(ubyte)[][] members...) {
887 //         Redis j = getShard(key);
888 //         return j.geopos(key, members);
889 //     }
890 
891 //     override
892 //     List!(GeoRadiusResponse) georadius(const(ubyte)[] key, double longitude, double latitude,
893 //             double radius, GeoUnit unit) {
894 //         Redis j = getShard(key);
895 //         return j.georadius(key, longitude, latitude, radius, unit);
896 //     }
897 
898 //     override
899 //     List!(GeoRadiusResponse) georadiusReadonly(const(ubyte)[] key, double longitude, double latitude,
900 //             double radius, GeoUnit unit) {
901 //         Redis j = getShard(key);
902 //         return j.georadiusReadonly(key, longitude, latitude, radius, unit);
903 //     }
904 
905 //     override
906 //     List!(GeoRadiusResponse) georadius(const(ubyte)[] key, double longitude, double latitude,
907 //             double radius, GeoUnit unit, GeoRadiusParam param) {
908 //         Redis j = getShard(key);
909 //         return j.georadius(key, longitude, latitude, radius, unit, param);
910 //     }
911 
912 //     override
913 //     List!(GeoRadiusResponse) georadiusReadonly(const(ubyte)[] key, double longitude, double latitude,
914 //             double radius, GeoUnit unit, GeoRadiusParam param) {
915 //         Redis j = getShard(key);
916 //         return j.georadiusReadonly(key, longitude, latitude, radius, unit, param);
917 //     }
918 
919 //     override
920 //     List!(GeoRadiusResponse) georadiusByMember(const(ubyte)[] key, const(ubyte)[] member, double radius,
921 //             GeoUnit unit) {
922 //         Redis j = getShard(key);
923 //         return j.georadiusByMember(key, member, radius, unit);
924 //     }
925 
926 //     override
927 //     List!(GeoRadiusResponse) georadiusByMemberReadonly(const(ubyte)[] key, const(ubyte)[] member, double radius,
928 //             GeoUnit unit) {
929 //         Redis j = getShard(key);
930 //         return j.georadiusByMemberReadonly(key, member, radius, unit);
931 //     }
932 
933 //     override
934 //     List!(GeoRadiusResponse) georadiusByMember(const(ubyte)[] key, const(ubyte)[] member, double radius,
935 //             GeoUnit unit, GeoRadiusParam param) {
936 //         Redis j = getShard(key);
937 //         return j.georadiusByMember(key, member, radius, unit, param);
938 //     }
939 
940 //     override
941 //     List!(GeoRadiusResponse) georadiusByMemberReadonly(const(ubyte)[] key, const(ubyte)[] member, double radius,
942 //             GeoUnit unit, GeoRadiusParam param) {
943 //         Redis j = getShard(key);
944 //         return j.georadiusByMemberReadonly(key, member, radius, unit, param);
945 //     }
946 
947 //     override
948 //     ScanResult!(MapEntry!(const(ubyte)[], const(ubyte)[])) hscan(const(ubyte)[] key, const(ubyte)[] cursor) {
949 //         Redis j = getShard(key);
950 //         return j.hscan(key, cursor);
951 //     }
952 
953 //     override
954 //     ScanResult!(MapEntry!(const(ubyte)[], const(ubyte)[])) hscan(const(ubyte)[] key, const(ubyte)[] cursor, ScanParams params) {
955 //         Redis j = getShard(key);
956 //         return j.hscan(key, cursor, params);
957 //     }
958 
959 //     override
960 //     ScanResult!(const(ubyte)[]) sscan(const(ubyte)[] key, const(ubyte)[] cursor) {
961 //         Redis j = getShard(key);
962 //         return j.sscan(key, cursor);
963 //     }
964 
965 //     override
966 //     ScanResult!(const(ubyte)[]) sscan(const(ubyte)[] key, const(ubyte)[] cursor, ScanParams params) {
967 //         Redis j = getShard(key);
968 //         return j.sscan(key, cursor, params);
969 //     }
970 
971 //     override
972 //     ScanResult!(Tuple) zscan(const(ubyte)[] key, const(ubyte)[] cursor) {
973 //         Redis j = getShard(key);
974 //         return j.zscan(key, cursor);
975 //     }
976 
977 //     override
978 //     ScanResult!(Tuple) zscan(const(ubyte)[] key, const(ubyte)[] cursor, ScanParams params) {
979 //         Redis j = getShard(key);
980 //         return j.zscan(key, cursor, params);
981 //     }
982 
983 //     override
984 //     List!(long) bitfield(const(ubyte)[] key, const(ubyte)[][] arguments...) {
985 //         Redis j = getShard(key);
986 //         return j.bitfield(key, arguments);
987 //  }
988 
989 //     override
990 //     Long hstrlen(const(ubyte)[] key, const(ubyte)[] field) {
991 //         Redis j = getShard(key);
992 //         return j.hstrlen(key, field);
993 //     }
994 
995 //     override
996 //     const(ubyte)[] xadd(const(ubyte)[] key, const(ubyte)[] id, Map!(const(ubyte)[], const(ubyte)[]) hash, long maxLen, bool approximateLength) {
997 //         Redis j = getShard(key);
998 //         return j.xadd(key, id, hash, maxLen, approximateLength);
999 //     }
1000 
1001 //     override
1002 //     Long xlen(const(ubyte)[] key) {
1003 //         Redis j = getShard(key);
1004 //         return j.xlen(key);
1005 //     }
1006 
1007 //     override
1008 //     List!(const(ubyte)[]) xrange(const(ubyte)[] key, const(ubyte)[] start, const(ubyte)[] end, long count) {
1009 //         Redis j = getShard(key);
1010 //         return j.xrange(key, start, end, count);
1011 //     }
1012 
1013 //     override
1014 //     List!(const(ubyte)[]) xrevrange(const(ubyte)[] key, const(ubyte)[] end, const(ubyte)[] start, int count) {
1015 //         Redis j = getShard(key);
1016 //         return j.xrevrange(key, end, start, count);
1017 //     }
1018 
1019 //     override
1020 //     Long xack(const(ubyte)[] key, const(ubyte)[] group, const(ubyte)[][] ids...) {
1021 //         Redis j = getShard(key);
1022 //         return j.xack(key, group, ids);
1023 //     }
1024 
1025 //     override
1026 //     string xgroupCreate(const(ubyte)[] key, const(ubyte)[] consumer, const(ubyte)[] id, bool makeStream) {
1027 //         Redis j = getShard(key);
1028 //         return j.xgroupCreate(key, consumer, id, makeStream);
1029 //     }
1030 
1031 //     override
1032 //     string xgroupSetID(const(ubyte)[] key, const(ubyte)[] consumer, const(ubyte)[] id) {
1033 //         Redis j = getShard(key);
1034 //         return j.xgroupSetID(key, consumer, id);
1035 //     }
1036 
1037 //     override
1038 //     Long xgroupDestroy(const(ubyte)[] key, const(ubyte)[] consumer) {
1039 //         Redis j = getShard(key);
1040 //         return j.xgroupDestroy(key, consumer);
1041 //     }
1042 
1043 //     override
1044 //     string xgroupDelConsumer(const(ubyte)[] key, const(ubyte)[] consumer, const(ubyte)[] consumerName) {
1045 //         Redis j = getShard(key);
1046 //         return j.xgroupDelConsumer(key, consumer, consumerName);
1047 //     }
1048 
1049 //     override
1050 //     Long xdel(const(ubyte)[] key, const(ubyte)[][] ids...) {
1051 //         Redis j = getShard(key);
1052 //         return j.xdel(key, ids);
1053 //     }
1054 
1055 //     override
1056 //     Long xtrim(const(ubyte)[] key, long maxLen, bool approximateLength) {
1057 //         Redis j = getShard(key);
1058 //         return j.xtrim(key, maxLen, approximateLength);
1059 //     }
1060 
1061 //     override
1062 //     List!(const(ubyte)[]) xpending(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] start, const(ubyte)[] end, int count, const(ubyte)[] consumername) {
1063 //         Redis j = getShard(key);
1064 //         return j.xpending(key, groupname, start, end, count, consumername);
1065 //     }
1066 
1067 //     override
1068 //     List!(const(ubyte)[]) xclaim(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] consumername, long minIdleTime, long newIdleTime,
1069 //             int retries, bool force, const(ubyte)[][] ids) {
1070 //         Redis j = getShard(key);
1071 //         return j.xclaim(key, groupname, consumername, minIdleTime, newIdleTime, retries, force, ids);
1072 //     }
1073 
1074 //     override
1075 //     Object sendCommand(ProtocolCommand cmd, const(ubyte)[][] args...) {
1076 //         // default since no sample key provided in RedisCommands interface
1077 //         const(ubyte)[] sampleKey = args.length > 0 ? args[0] : cast(const(ubyte)[])(cmd.to!string());
1078 //         Redis j = getShard(args[0]);
1079 //         return j.sendCommand(cmd, args);
1080 //     }
1081 
1082 }