@Override public CompletableFuture<Void> close() { CompletableFuture<Void> future = new CompletableFuture<>(); lock.lock() .thenCompose(v -> balancer.replace(server.server().cluster())) .whenComplete( (r1, e1) -> { balancer.close(); lock.unlock() .whenComplete( (r2, e2) -> { super.close() .whenComplete( (r3, e3) -> { server .close() .whenComplete( (r4, e4) -> { if (e4 == null) { future.complete(null); } else { future.completeExceptionally(e4); } }); }); }); }); return future; }
/** Registers membership change listeners on the cluster. */ private void registerListeners() { server .server() .cluster() .members() .forEach( m -> { m.onTypeChange(t -> balance()); m.onStatusChange(s -> balance()); }); server.server().cluster().onLeaderElection(l -> balance()); server .server() .cluster() .onJoin( m -> { m.onTypeChange(t -> balance()); m.onStatusChange(s -> balance()); balance(); }); server.server().cluster().onLeave(m -> balance()); }
/** Balances the cluster. */ private void balance() { if (lock != null && !locking && server.server().cluster().member().equals(server.server().cluster().leader())) { locking = true; lock.lock() .thenCompose(v -> balancer.balance(server.server().cluster())) .whenComplete((r1, e1) -> lock.unlock().whenComplete((r2, e2) -> locking = false)); } }
@Override public CompletableFuture<Atomix> open() { return server .open() .thenRun(this::registerListeners) .thenCompose(v -> super.open()) .thenCompose(v -> client.get("", DistributedLock.class)) .thenApply( lock -> { this.lock = lock; return this; }); }