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.RedisSlotBasedConnectionHandler; 13 14 import hunt.redis.RedisClusterConnectionHandler; 15 16 import hunt.redis.Exceptions; 17 import hunt.redis.HostAndPort; 18 import hunt.redis.Redis; 19 import hunt.redis.RedisPool; 20 21 import hunt.text.Common; 22 23 import hunt.collection.List; 24 import hunt.collection.Set; 25 import hunt.pool.impl.GenericObjectPoolConfig; 26 27 28 class RedisSlotBasedConnectionHandler : RedisClusterConnectionHandler { 29 30 this(Set!(HostAndPort) nodes, 31 GenericObjectPoolConfig poolConfig, int timeout) { 32 this(nodes, poolConfig, timeout, timeout); 33 } 34 35 this(Set!(HostAndPort) nodes, 36 GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout) { 37 super(nodes, poolConfig, connectionTimeout, soTimeout, null); 38 } 39 40 this(Set!(HostAndPort) nodes, GenericObjectPoolConfig poolConfig, 41 int connectionTimeout, int soTimeout, string password) { 42 super(nodes, poolConfig, connectionTimeout, soTimeout, password); 43 } 44 45 this(Set!(HostAndPort) nodes, GenericObjectPoolConfig poolConfig, 46 int connectionTimeout, int soTimeout, string password, string clientName) { 47 super(nodes, poolConfig, connectionTimeout, soTimeout, password, clientName); 48 } 49 50 // this(Set!(HostAndPort) nodes, GenericObjectPoolConfig poolConfig, int connectionTimeout, 51 // int soTimeout, string password, string clientName, 52 // bool ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, 53 // HostnameVerifier hostnameVerifier, RedisClusterHostAndPortMap portMap) { 54 55 // super(nodes, poolConfig, connectionTimeout, soTimeout, password, clientName, ssl, 56 // sslSocketFactory, sslParameters, hostnameVerifier, portMap); 57 // } 58 59 override 60 Redis getConnection() { 61 // In antirez's redis-rb-cluster implementation, 62 // getRandomConnection always return valid connection (able to 63 // ping-pong) 64 // or exception if all connections are invalid 65 66 List!(RedisPool) pools = cache.getShuffledNodesPool(); 67 68 foreach(RedisPool pool ; pools) { 69 Redis redis = null; 70 try { 71 redis = pool.getResource(); 72 73 if (redis is null) { 74 continue; 75 } 76 77 string result = redis.ping(); 78 79 if (result.equalsIgnoreCase("pong")) return redis; 80 81 redis.close(); 82 } catch (RedisException ex) { 83 if (redis !is null) { 84 redis.close(); 85 } 86 } 87 } 88 89 throw new RedisNoReachableClusterNodeException("No reachable node in cluster"); 90 } 91 92 override 93 Redis getConnectionFromSlot(int slot) { 94 RedisPool connectionPool = cache.getSlotPool(slot); 95 if (connectionPool !is null) { 96 // It can't guaranteed to get valid connection because of node 97 // assignment 98 return connectionPool.getResource(); 99 } else { 100 renewSlotCache(); //It's abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state 101 connectionPool = cache.getSlotPool(slot); 102 if (connectionPool !is null) { 103 return connectionPool.getResource(); 104 } else { 105 //no choice, fallback to new connection to random node 106 return getConnection(); 107 } 108 } 109 } 110 }