1 module hunt.cache.adapter.RedisClusterAdapter;
2 
3 import hunt.cache.adapter.Adapter;
4 import hunt.cache.CacheOptions;
5 import hunt.cache.Nullable;
6 import hunt.cache.Store;
7 
8 import hunt.collection.HashSet;
9 import hunt.collection.Set;
10 import hunt.Exceptions;
11 import hunt.logging;
12 import hunt.redis;
13 
14 import std.array;
15 import std.conv;
16 import std.string;
17 
18 class RedisClusterAdapter : Adapter
19 {
20     this(RedisPoolOptions poolConfig, RedisClusterConfig clusterConfig)
21     {
22         // try
23         // {            
24         //     _redis = new RedisCluster(new HostAndPort(poolConfig.host, poolConfig.port));
25 
26         //     // if (!poolConfig.password.empty())
27         //     //     _redis.auth(poolConfig.password);
28         //     // _redis.select(poolConfig.database);
29         // }
30         // catch (Exception e)
31         // {
32         //     logError(e);
33         // }
34 
35         HostAndPort[] clusterNode;
36         string[] hostPorts = clusterConfig.nodes;
37         
38         foreach(string item; hostPorts) {
39             string[] hostPort = item.split(":");
40             if(hostPort.length < 2) {
41                 warningf("Wrong host and port: %s", item);
42                 continue;
43             }
44 
45             version(HUNT_DEBUG) {
46                 tracef("Cluster host: %s", hostPort);
47             }
48 
49             try {
50                 int port = to!int(hostPort[1]);
51                 clusterNode ~= new HostAndPort(hostPort[0], port);
52             } catch(Exception ex) {
53                 warning(ex);
54             }
55         }
56 
57         _redis = new RedisCluster(clusterNode, poolConfig);
58     }
59 
60     Nullable!V get(V) (string key)
61     {
62         synchronized(this)
63         {   
64             try {
65                 string data = _redis.get(key);
66                 return DeserializeToObject!V(cast(byte[])data);
67             } catch(Exception ex) {
68                 warning(ex.msg);
69                 version(HUNT_DEBUG) warning(ex);
70             }
71             return Nullable!V();
72         }
73     }
74 
75     Nullable!V[string] getAll(V) (string[] keys)
76     {
77         synchronized(this)
78         {
79             Nullable!V[string] mapv;
80             if( keys.length == 0)
81                 return mapv;
82 
83             List!(string) r = _redis.mget(keys);
84 
85             foreach(i, v ; r)
86             {
87                 mapv[keys[i]] = DeserializeToObject!V(cast(byte[])v);
88             }
89 
90             return mapv;
91         }
92     }
93 
94     bool hasKey(string key)
95     {
96         synchronized(this)
97         {
98             return _redis.exists(key);
99         }
100     }
101 
102     void set(V) (string key,  V v, uint expired)
103     {
104         synchronized(this)
105         {
106             if( expired == 0)
107                 _redis.set(key, cast(string)SerializeToByte(v));
108             else {
109                 implementationMissing(false);
110             }
111                 // _redis.setex(key, expired, cast(string)SerializeToByte(v));
112         }
113     }
114 
115     bool setIfAbsent(V) (string key,  V v)
116     {
117         synchronized(this)
118         {
119             return _redis.setnx(key, cast(string)SerializeToByte(v)) == 1;        
120         }
121     }
122 
123     void set(V) (V[string] maps, uint expired)
124     {
125         synchronized(this)
126         {
127             if(maps.length == 0)
128                 return;
129 
130             if(expired == 0)
131             {
132                 _redis.mset(maps);
133             }
134             else
135             {
136                 foreach( k, v ; maps)
137                 {
138                     _redis.set(k, expired, cast(string)SerializeToByte(v));
139                 }
140             }
141         }
142     }
143 
144     bool remove(string key)
145     {
146         synchronized(this)
147         {
148             return _redis.del(key) > 0;
149         }
150     }
151 
152     void remove(string[] keys)
153     {
154         synchronized(this)
155         {
156             if( keys.length == 0)
157                 return ;
158 
159             foreach(key ; keys){
160                 _redis.del(key);
161             }
162         }
163     }
164 
165     void clear()
166     {
167         synchronized(this)
168         {
169             // _redis.flushAll();
170         }
171     }
172 
173 protected:
174     RedisCluster _redis;
175 }