1 module hunt.cache.Cache; 2 3 import hunt.cache.adapter; 4 import hunt.cache.CacheOptions; 5 import hunt.cache.Defined; 6 import hunt.cache.Nullable; 7 import hunt.logging.ConsoleLogger; 8 9 import std.algorithm; 10 import std.array; 11 import std.conv : to; 12 import std.range; 13 14 final class Cache 15 { 16 this(MemoryAdapter memoryAdapter) { 17 this(memoryAdapter, new CacheOptions()); 18 } 19 20 this(Object adapterObject, CacheOptions option, MemoryAdapter memoryAdapter = null) 21 { 22 version(HUNT_DEBUG) infof("Creating cache: [%s]", option); 23 _option = option; 24 auto className = typeid(adapterObject); 25 26 if (memoryAdapter !is null && typeid(memoryAdapter) != className) 27 { 28 _memoryAdapter = memoryAdapter; 29 _l2enabled = true; 30 } 31 32 if(className == typeid(MemoryAdapter)) 33 { 34 _memoryAdapter = cast(MemoryAdapter)adapterObject; 35 _type = CACHE_ADAPTER.MEMORY; 36 return; 37 } 38 39 if(className == typeid(RedisAdapter)) 40 { 41 _redisAdapter = cast(RedisAdapter)adapterObject; 42 _type = CACHE_ADAPTER.REDIS; 43 return; 44 } 45 46 if(className == typeid(RedisClusterAdapter)) 47 { 48 _redisClusterAdapter = cast(RedisClusterAdapter)adapterObject; 49 _type = CACHE_ADAPTER.REDIS_CLUSTER; 50 return; 51 } 52 53 // version(WITH_HUNT_MEMCACHE) 54 // { 55 // if(className == typeid(MemcacheAdapter)) 56 // { 57 // _memcacheAdapter = cast(MemcacheAdapter)(adapterObject); 58 // _type = CACHE_ADAPTER.MEMCACHE_ADAPTER; 59 // return; 60 // } 61 // } 62 63 version(WITH_HUNT_ROCKSDB) 64 { 65 if(className == typeid(RocksdbAdapter)) 66 { 67 _rocksdbAdapter = cast(RocksdbAdapter)(adapterObject); 68 _type = CACHE_ADAPTER.ROCKSDB; 69 return; 70 } 71 } 72 } 73 74 75 76 Nullable!V get(V = string) (string key) 77 { 78 switch(_type) 79 { 80 case CACHE_ADAPTER.MEMORY: 81 return get!(MemoryAdapter, V)(key); 82 83 case CACHE_ADAPTER.REDIS: 84 return get!(RedisAdapter, V)(key); 85 86 case CACHE_ADAPTER.REDIS_CLUSTER: 87 return get!(RedisClusterAdapter, V)(key); 88 89 // version(WITH_HUNT_MEMCACHE) 90 // { 91 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 92 // return get!(MemcacheAdapter, V)(key); 93 // } 94 95 version(WITH_HUNT_ROCKSDB) 96 { 97 case CACHE_ADAPTER.ROCKSDB: 98 return get!(RocksdbAdapter, V)(key); 99 } 100 101 default: 102 return get!(MemoryAdapter, V)(key); 103 } 104 } 105 106 private Nullable!V get(A, V) (string key) 107 { 108 if(!_option.prefix.empty()) 109 key = _option.prefix ~ key; 110 111 version(HUNT_CACHE_DEBUG) trace("key: ", key); 112 113 synchronized(this) 114 { 115 if (_l2enabled) 116 { 117 auto v1 = _memoryAdapter.get!V(key); 118 if(!v1.isNull) 119 return v1; 120 } 121 122 auto v2 = cacheAdapter!A().get!V(key); 123 if(v2.isNull) 124 return v2; 125 126 if (_l2enabled) 127 { 128 _memoryAdapter.set!V(key, v2.origin); 129 } 130 131 return v2; 132 } 133 } 134 135 136 Nullable!V[string] get(V = string) (string[] keys) 137 { 138 switch(_type) 139 { 140 case CACHE_ADAPTER.MEMORY: 141 return get!(MemoryAdapter, V)(keys); 142 143 case CACHE_ADAPTER.REDIS: 144 return get!(RedisAdapter, V)(keys); 145 146 case CACHE_ADAPTER.REDIS_CLUSTER: 147 return get!(RedisClusterAdapter, V)(keys); 148 149 // version(WITH_HUNT_MEMCACHE) 150 // { 151 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 152 // return get!(MemcacheAdapter, V)(keys); 153 // } 154 155 version(WITH_HUNT_ROCKSDB) 156 { 157 case CACHE_ADAPTER.ROCKSDB: 158 return get!(RocksdbAdapter, V)(keys); 159 } 160 161 default: 162 return get!(MemoryAdapter, V)(keys); 163 } 164 } 165 166 private Nullable!V[string] get(A, V) (string[] keys) 167 { 168 if(!_option.prefix.empty()) { 169 keys = keys.map!(k => _option.prefix ~ k)(); 170 } 171 172 synchronized(this) 173 { 174 Nullable!V[string] mapv; 175 foreach(k ; keys) 176 { 177 mapv[k] = get!(A, V)(k); 178 } 179 180 return mapv; 181 } 182 } 183 184 bool hasKey(string key) 185 { 186 switch(_type) 187 { 188 case CACHE_ADAPTER.MEMORY: 189 return hasKey!MemoryAdapter(key); 190 191 case CACHE_ADAPTER.REDIS: 192 return hasKey!RedisAdapter(key); 193 194 case CACHE_ADAPTER.REDIS_CLUSTER: 195 return hasKey!RedisClusterAdapter(key); 196 197 // version(WITH_HUNT_MEMCACHE) 198 // { 199 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 200 // return hasKey!MemcacheAdapter(key); 201 // } 202 version(WITH_HUNT_ROCKSDB) 203 { 204 case CACHE_ADAPTER.ROCKSDB: 205 return hasKey!RocksdbAdapter(key); 206 } 207 default: 208 return hasKey!MemoryAdapter(key); 209 } 210 } 211 212 bool hasKey(A)(string key) 213 { 214 if(!_option.prefix.empty()) 215 key = _option.prefix ~ key; 216 217 synchronized(this) 218 { 219 return cacheAdapter!A().hasKey(key); 220 } 221 } 222 223 224 void set(V) (string key, V v, uint expired = 0) 225 { 226 switch(_type) 227 { 228 case CACHE_ADAPTER.MEMORY: 229 return set!(MemoryAdapter, V)(key, v, expired); 230 231 case CACHE_ADAPTER.REDIS: 232 return set!(RedisAdapter, V)(key, v, expired); 233 234 case CACHE_ADAPTER.REDIS_CLUSTER: 235 return set!(RedisClusterAdapter, V)(key, v, expired); 236 237 // version(WITH_HUNT_MEMCACHE) 238 // { 239 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 240 // return set!(MemcacheAdapter, V)(key, v, expired); 241 // } 242 243 version(WITH_HUNT_ROCKSDB) 244 { 245 case CACHE_ADAPTER.ROCKSDB: 246 return set!(RocksdbAdapter, V)(key, v, expired); 247 } 248 249 default: 250 return set!(MemoryAdapter, V)(key, v, expired); 251 } 252 } 253 254 private void set(A, V) (string key, V v, uint expired = 0) 255 { 256 if(!_option.prefix.empty()) 257 key = _option.prefix ~ key; 258 259 version(HUNT_CACHE_DEBUG) trace("key: ", key); 260 261 synchronized(this) 262 { 263 cacheAdapter!A().set!V(key, v, expired); 264 265 if (_l2enabled) 266 { 267 _memoryAdapter.set!V(key, v, expired); 268 } 269 } 270 } 271 272 bool setIfAbsent(V) (string key, V v) 273 { 274 if(!_option.prefix.empty()) 275 key = _option.prefix ~ key; 276 277 synchronized(this) 278 { 279 if(cacheAdapter!A().setIfAbsent!V(key, v)) 280 { 281 if (_l2enabled) 282 { 283 _memoryAdapter.set!V(key, v); 284 } 285 286 return true; 287 } 288 } 289 290 return false; 291 } 292 293 void set(V) (V[string] maps, uint expired = 0) 294 { 295 switch(_type) 296 { 297 case CACHE_ADAPTER.MEMORY: 298 return set!(MemoryAdapter, V)(maps, expired); 299 300 case CACHE_ADAPTER.REDIS: 301 return set!(RedisAdapter, V)(maps, expired); 302 303 case CACHE_ADAPTER.REDIS_CLUSTER: 304 return set!(RedisClusterAdapter, V)(maps, expired); 305 306 case CACHE_ADAPTER.MEMCACHE_ADAPTER: 307 return set!(MemcacheAdapter, V)(maps, expired); 308 case CACHE_ADAPTER.ROCKSDB: 309 return set!(RocksdbAdapter, V)(maps, expired); 310 default: 311 return set!(MemoryAdapter, V)(maps, expired); 312 } 313 } 314 315 private void set(A, V) (V[string] maps, uint expired = 0) 316 { 317 synchronized(this) 318 { 319 cacheAdapter!A().set!V(maps, expired); 320 if (_l2enabled) 321 { 322 _memoryAdapter.set!V(maps, expired); 323 } 324 } 325 } 326 327 bool remove(string key) 328 { 329 switch(_type) 330 { 331 case CACHE_ADAPTER.MEMORY: 332 return remove!MemoryAdapter(key); 333 334 case CACHE_ADAPTER.REDIS: 335 return remove!RedisAdapter(key); 336 337 case CACHE_ADAPTER.REDIS_CLUSTER: 338 return remove!RedisClusterAdapter(key); 339 340 // version(WITH_HUNT_MEMCACHE) 341 // { 342 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 343 // return remove!MemcacheAdapter(key); 344 // } 345 version(WITH_HUNT_ROCKSDB) 346 { 347 case CACHE_ADAPTER.ROCKSDB: 348 return remove!RocksdbAdapter(key); 349 } 350 default: 351 return remove!MemoryAdapter(key); 352 } 353 } 354 355 private bool remove(A)(string key) 356 { 357 if(!_option.prefix.empty()) 358 key = _option.prefix ~ key; 359 360 synchronized(this) 361 { 362 auto ret = cacheAdapter!A().remove(key); 363 if (_l2enabled) 364 { 365 _memoryAdapter.remove(key); 366 } 367 return ret; 368 } 369 } 370 371 void remove(string[] keys) 372 { 373 switch(_type) 374 { 375 case CACHE_ADAPTER.MEMORY: 376 remove!MemoryAdapter(keys); 377 break; 378 379 case CACHE_ADAPTER.REDIS: 380 remove!RedisAdapter(keys); 381 break; 382 383 case CACHE_ADAPTER.REDIS_CLUSTER: 384 remove!RedisClusterAdapter(keys); 385 break; 386 387 // version(WITH_HUNT_MEMCACHE) 388 // { 389 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 390 // remove!MemcacheAdapter(keys); 391 // break; 392 // } 393 394 version(WITH_HUNT_ROCKSDB) 395 { 396 case CACHE_ADAPTER.ROCKSDB: 397 remove!RocksdbAdapter(keys); 398 break; 399 } 400 401 default: 402 remove!MemoryAdapter(keys); 403 } 404 } 405 406 private void remove(A)(string[] keys) 407 { 408 if(!_option.prefix.empty()) { 409 keys = keys.map!(k => _option.prefix ~ k)().array(); 410 } 411 412 synchronized(this) 413 { 414 cacheAdapter!A().remove(keys); 415 if (_l2enabled) 416 { 417 _memoryAdapter.remove(keys); 418 } 419 } 420 } 421 422 void clear() 423 { 424 switch(_type) 425 { 426 case CACHE_ADAPTER.MEMORY: 427 clear!MemoryAdapter(); 428 break; 429 430 case CACHE_ADAPTER.REDIS: 431 clear!RedisAdapter(); 432 break; 433 434 case CACHE_ADAPTER.REDIS_CLUSTER: 435 clear!RedisClusterAdapter(); 436 break; 437 438 // version(WITH_HUNT_MEMCACHE) 439 // { 440 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 441 // clear!MemcacheAdapter(); 442 // break; 443 // } 444 445 version(WITH_HUNT_ROCKSDB) 446 { 447 case CACHE_ADAPTER.ROCKSDB: 448 clear!RocksdbAdapter(); 449 break; 450 } 451 452 default: 453 clear!MemoryAdapter(); 454 } 455 } 456 457 private void clear(A)() 458 { 459 synchronized(this) 460 { 461 cacheAdapter!A().clear(); 462 463 if (_l2enabled) 464 { 465 _memoryAdapter.clear(); 466 } 467 } 468 } 469 470 private A cacheAdapter(A)() 471 { 472 switch(_type) 473 { 474 case CACHE_ADAPTER.MEMORY: 475 return cast(A)_memoryAdapter; 476 477 case CACHE_ADAPTER.REDIS: 478 return cast(A)_redisAdapter; 479 480 // version(WITH_HUNT_MEMCACHE) 481 // { 482 // case CACHE_ADAPTER.MEMCACHE_ADAPTER: 483 // return cast(A)_memcacheAdapter; 484 // } 485 version(WITH_HUNT_ROCKSDB) 486 { 487 case CACHE_ADAPTER.ROCKSDB: 488 return cast(A)_rocksdbAdapter; 489 } 490 default: 491 return cast(A)_memoryAdapter; 492 } 493 } 494 495 private 496 { 497 bool _l2enabled = false; 498 499 MemoryAdapter _memoryAdapter; 500 RedisAdapter _redisAdapter; 501 RedisClusterAdapter _redisClusterAdapter; 502 // version(WITH_HUNT_MEMCACHE) MemcacheAdapter _memcacheAdapter; 503 version(WITH_HUNT_ROCKSDB) RocksdbAdapter _rocksdbAdapter; 504 505 CacheOptions _option; 506 507 CACHE_ADAPTER _type; 508 } 509 }