/** * Registers the given {@code member} with given {@code loadFactor} and {@code commandFilter} if it is not * already contained in the {@link ConsistentHash}. It will return the current ConsistentHash if the addition is * a duplicate and returns a new ConsistentHash with updated memberships if it is not. * <p> * The relative loadFactor of the member determines the likelihood of being selected as a destination for a command. * * @param member the member to register * @param loadFactor the load factor of the new member * @param commandFilter filter describing which commands can be handled by the given member * @return a new {@link ConsistentHash} instance with updated memberships */ public ConsistentHash with(Member member, int loadFactor, CommandMessageFilter commandFilter) { Assert.notNull(member, () -> "Member may not be null"); ConsistentHashMember newMember = new ConsistentHashMember(member, loadFactor, commandFilter); if (members.containsKey(member.name()) && newMember.equals(members.get(member.name()))) { return this; } Map<String, ConsistentHashMember> newMembers = new TreeMap<>(members); newMembers.put(member.name(), newMember); return new ConsistentHash(newMembers, hashFunction, modCount + 1); }
private ConsistentHash(Map<String, ConsistentHashMember> members, Function<String, String> hashFunction, int modCount) { this.hashFunction = hashFunction; this.modCount = modCount; this.hashToMember = new TreeMap<>(); this.members = members; members.values().forEach(m -> m.hashes().forEach(h -> hashToMember.put(h, m))); }
/** * Returns the hashes covered by the member. If the hash of the routing key matches with one of the returned * hashes and the member is capable of handling the command then it will be selected as a target for the * command. * * @return the hashes covered by this member */ public Set<String> hashes() { return IntStream.range(0, segmentCount) .mapToObj(i -> hash(name() + " #" + i)) .collect(Collectors.toSet()); }
/** * Registers the given {@code member} with given {@code loadFactor} and {@code commandFilter} if it is not * already contained in the {@link ConsistentHash}. It will return the current ConsistentHash if the addition is * a duplicate and returns a new ConsistentHash with updated memberships if it is not. * <p> * The relative loadFactor of the member determines the likelihood of being selected as a destination for a command. * * @param member the member to register * @param loadFactor the load factor of the new member * @param commandFilter filter describing which commands can be handled by the given member * @return a new {@link ConsistentHash} instance with updated memberships */ public ConsistentHash with(Member member, int loadFactor, Predicate<? super CommandMessage<?>> commandFilter) { Assert.notNull(member, () -> "Member may not be null"); ConsistentHashMember newMember = new ConsistentHashMember(member, loadFactor, commandFilter); if (members.containsKey(member.name()) && newMember.equals(members.get(member.name()))) { return this; } Map<String, ConsistentHashMember> newMembers = new TreeMap<>(members); newMembers.put(member.name(), newMember); return new ConsistentHash(newMembers, hashFunction, modCount + 1); }
/** * Registers the given {@code member} with given {@code loadFactor} and {@code commandFilter} if it is not * already contained in the {@link ConsistentHash}. It will return the current ConsistentHash if the addition is * a duplicate and returns a new ConsistentHash with updated memberships if it is not. * <p> * The relative loadFactor of the member determines the likelihood of being selected as a destination for a command. * * @param member the member to register * @param loadFactor the load factor of the new member * @param commandFilter filter describing which commands can be handled by the given member * @return a new {@link ConsistentHash} instance with updated memberships */ public ConsistentHash with(Member member, int loadFactor, CommandMessageFilter commandFilter) { Assert.notNull(member, () -> "Member may not be null"); ConsistentHashMember newMember = new ConsistentHashMember(member, loadFactor, commandFilter); if (members.containsKey(member.name()) && newMember.equals(members.get(member.name()))) { return this; } Map<String, ConsistentHashMember> newMembers = new TreeMap<>(members); newMembers.put(member.name(), newMember); return new ConsistentHash(newMembers, hashFunction, modCount + 1); }
/** * Returns the hashes covered by the member. If the hash of the routing key matches with one of the returned * hashes and the member is capable of handling the command then it will be selected as a target for the * command. * * @return the hashes covered by this member */ public Set<String> hashes() { Set<String> newHashes = new TreeSet<>(); for (int t = 0; t < segmentCount; t++) { String hash = hash(name() + " #" + t); newHashes.add(hash); } return newHashes; }
/** * Returns the hashes covered by the member. If the hash of the routing key matches with one of the returned * hashes and the member is capable of handling the command then it will be selected as a target for the * command. * * @return the hashes covered by this member */ public Set<String> hashes() { Set<String> newHashes = new TreeSet<>(); for (int t = 0; t < segmentCount; t++) { String hash = hash(name() + " #" + t); newHashes.add(hash); } return newHashes; }
@Override public String toString() { StringBuilder sb = new StringBuilder("ConsistentHash ["); Collection<ConsistentHashMember> members = this.members.values(); members.forEach(m -> sb.append(m.toString()).append(",")); if (!members.isEmpty()) { sb.delete(sb.length() - 1, sb.length()); } sb.append("]"); return sb.toString(); }
private ConsistentHash(Map<String, ConsistentHashMember> members, Function<String, String> hashFunction, int modCount) { this.hashFunction = hashFunction; this.modCount = modCount; this.hashToMember = new TreeMap<>(); this.members = members; members.values().forEach(m -> m.hashes().forEach(h -> hashToMember.put(h, m))); }
private ConsistentHash(Map<String, ConsistentHashMember> members, Function<String, String> hashFunction, int modCount) { this.hashFunction = hashFunction; this.modCount = modCount; this.hashToMember = new TreeMap<>(); this.members = members; members.values().forEach(m -> m.hashes().forEach(h -> hashToMember.put(h, m))); }
@Override public String toString() { StringBuilder sb = new StringBuilder("ConsistentHash ["); Collection<ConsistentHashMember> members = this.members.values(); members.forEach(m -> sb.append(m.toString()).append(",")); if (!members.isEmpty()) { sb.delete(sb.length() - 1, sb.length()); } sb.append("]"); return sb.toString(); }