@Override public CompletableFuture<Void> consume(long index, Consumer<LogRecord> consumer) { return term().thenCompose(term -> { protocol.registerRecordsConsumer(subject, this::handleRecords, threadContext); this.consumer = consumer; this.index = index - 1; return register(term.primary().memberId()); }); } }
@Override public MemberId primary() { return Futures.get(election.getTerm()) .primary() .memberId(); }
@Override public MemberId primary() { return Futures.get(election.getTerm()) .primary() .memberId(); }
@Override public CompletableFuture<Long> append(byte[] value) { CompletableFuture<Long> future = new CompletableFuture<>(); term().thenCompose(term -> protocol.append(term.primary().memberId(), AppendRequest.request(value))) .whenCompleteAsync((response, error) -> { if (error == null) { if (response.status() == LogResponse.Status.OK) { future.complete(response.index()); } else { future.completeExceptionally(new PrimitiveException.Unavailable()); } } else { future.completeExceptionally(error); } }, threadContext); return future; } }
@Override public CompletableFuture<Void> close() { CompletableFuture<Void> future = new CompletableFuture<>(); PrimaryTerm term = this.term; if (term.primary() != null) { protocol.close(term.primary().memberId(), new CloseRequest(descriptor, sessionId.id())) .whenCompleteAsync((response, error) -> { try { protocol.unregisterEventListener(sessionId); clusterMembershipService.removeListener(membershipEventListener); primaryElection.removeListener(primaryElectionListener); } finally { future.complete(null); } }, threadContext); } else { future.complete(null); } return future; }
/** * Returns the current server role. * * @return the current server role */ public Role getRole() { return Objects.equals(Futures.get(primaryElection.getTerm()).primary().memberId(), clusterMembershipService.getLocalMember().id()) ? Role.PRIMARY : Role.BACKUP; }
/** * Handles a cluster event. */ private void handleClusterEvent(ClusterMembershipEvent event) { PrimaryTerm term = this.term; if (term != null && event.type() == ClusterMembershipEvent.Type.MEMBER_REMOVED && event.subject().id().equals(term.primary().memberId())) { threadContext.execute(() -> { state = PrimitiveState.SUSPENDED; stateChangeListeners.forEach(l -> l.accept(state)); }); } }
/** * Returns the current server role. * * @return the current server role */ public DistributedLogServer.Role getRole() { return Objects.equals(Futures.get(primaryElection.getTerm()).primary().memberId(), clusterMembershipService.getLocalMember().id()) ? DistributedLogServer.Role.LEADER : DistributedLogServer.Role.FOLLOWER; }
/** * Handles a replica change event. */ private void changeReplicas(PrimaryTerm term) { threadContext.execute(() -> { if (this.term == null || term.term() > this.term.term()) { this.term = term; consumer.register(term.primary().memberId()); } }); }
/** * Recursively connects to the partition. */ private void connect(int attempt, CompletableFuture<SessionClient> future) { if (attempt > MAX_ATTEMPTS) { future.completeExceptionally(new PrimitiveException.Unavailable()); return; } primaryElection.getTerm().whenCompleteAsync((term, error) -> { if (error == null) { if (term.primary() == null) { future.completeExceptionally(new PrimitiveException.Unavailable()); } else { this.term = term; protocol.registerEventListener(sessionId, this::handleEvent, threadContext); future.complete(this); } } else { Throwable cause = Throwables.getRootCause(error); if (cause instanceof PrimitiveException.Unavailable || cause instanceof TimeoutException) { threadContext.schedule(Duration.ofMillis(RETRY_DELAY), () -> connect(attempt + 1, future)); } else { future.completeExceptionally(new PrimitiveException.Unavailable()); } } }, threadContext); }
/** * Handles a cluster event. */ private void handleClusterEvent(ClusterMembershipEvent event) { PrimaryTerm term = this.term; if (term != null && event.type() == ClusterMembershipEvent.Type.MEMBER_REMOVED && event.subject().id().equals(term.primary().memberId())) { changeState(PrimitiveState.SUSPENDED); } }
&& Objects.equals(currentTerm.primary(), primary) && Objects.equals(currentTerm.candidates(), candidates) ? currentTerm() : incrementTerm();
log.trace("Sending {} to {}", request, term.primary()); PrimaryTerm term = this.term; if (term.primary() != null) { protocol.execute(term.primary().memberId(), request).whenCompleteAsync((response, error) -> { if (error == null) { log.trace("Received {}", response); primaryElection.getTerm().whenComplete((newTerm, termError) -> { if (termError == null) { if (newTerm.term() > term.term() && newTerm.primary() != null) { execute(operation).whenComplete(future); } else {
@Override public CompletableFuture<byte[]> execute(PrimitiveOperation operation) { ComposableFuture<byte[]> future = new ComposableFuture<>(); threadContext.execute(() -> { if (term.primary() == null) { primaryElection.getTerm().whenCompleteAsync((term, error) -> { if (error == null) { if (term.term() <= this.term.term() || term.primary() == null) { future.completeExceptionally(new PrimitiveException.Unavailable()); } else { this.term = term; execute(operation, 1, future); } } else { future.completeExceptionally(new PrimitiveException.Unavailable()); } }, threadContext); } else { execute(operation, 1, future); } }); return future; }
@Override public MemberId primary() { return Futures.get(election.getTerm()) .primary() .memberId(); }
/** * Returns the current server role. * * @return the current server role */ public DistributedLogServer.Role getRole() { return Objects.equals(Futures.get(primaryElection.getTerm()).primary().memberId(), clusterMembershipService.getLocalMember().id()) ? DistributedLogServer.Role.LEADER : DistributedLogServer.Role.FOLLOWER; }
/** * Handles a replica change event. */ private void changeReplicas(PrimaryTerm term) { threadContext.execute(() -> { if (this.term == null || term.term() > this.term.term()) { this.term = term; consumer.register(term.primary().memberId()); } }); }
/** * Handles a cluster event. */ private void handleClusterEvent(ClusterMembershipEvent event) { PrimaryTerm term = this.term; if (term != null && event.type() == ClusterMembershipEvent.Type.MEMBER_REMOVED && event.subject().id().equals(term.primary().memberId())) { changeState(PrimitiveState.SUSPENDED); } }