in iep-spring-leader-redis-cluster/src/main/java/com/netflix/iep/leader/redis/RedisClusterLeaderDatabase.java [153:211]
public boolean removeLeadershipFor(ResourceId resourceId) {
// note slight race here where the follower could overtake the leader if it fails. In that
// case, the watch and transaction should fail and we'd return a false.
String key = getKey(resourceId);
int slot = JedisClusterCRC16.getSlot(key);
try {
try (Jedis client = jedis.leaderForSlot(slot)) {
String watchResult = client.watch(key);
if (watchResult == null || !watchResult.equals("OK")) {
logger.warn("Invalid watch response: {}", watchResult);
return false;
}
try {
// now we check for leadership since we're on a watch
String data = client.get(key);
if (data == null || !data.equals(leaderString)) {
// lost the race but hey, still won.
logger.warn("Tried to remove leadership but it was already set to {}", data);
return true;
} else {
Transaction transaction = client.multi();
transaction.del(key);
List<Object> results = transaction.exec();
if (results == null ||
results.isEmpty() ||
results.get(0) == null ||
((long) results.get(0)) < 1) {
logger.error("Failed to delete the leader key for {}", key);
return false;
} else {
data = client.get(key);
if (data != null) {
logger.error("Tried to remove ourselves as leader for {} but it was still marked for {}", key, data);
return false;
} else {
logger.info("Removed ourselves as leader for key {}", key);
return true;
}
}
}
} catch (Exception ex) {
logger.error("Failed to delete key {}", key, ex);
return false;
} finally {
// transactions unset the watch but we also have a get() call before the
// transaction so we need to make sure to release that watch just in case
// something goes wrong between the get parsing and transaction execution.
String unwatchResult = client.unwatch();
if (unwatchResult == null || !unwatchResult.equals("OK")) {
logger.warn("Failure unwatching: {}", unwatchResult);
}
}
}
} catch (Exception ex) {
logger.error("Unexpected exception removing leader key: {}", key, ex);
return false;
}
}