io.atomix.protocols.raft.protocol.RaftResponse Java Examples

The following examples show how to use io.atomix.protocols.raft.protocol.RaftResponse. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LeaderRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<PollResponse> onPoll(final PollRequest request) {
  logRequest(request);

  // If a member sends a PollRequest to the leader, that indicates that it likely healed from
  // a network partition and may have had its status set to UNAVAILABLE by the leader. In order
  // to ensure heartbeats are immediately stored to the member, update its status if necessary.
  RaftMemberContext member = raft.getCluster().getMemberState(request.candidate());
  if (member != null) {
    member.resetFailureCount();
  }

  return CompletableFuture.completedFuture(logResponse(PollResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withTerm(raft.getTerm())
      .withAccepted(false)
      .build()));
}
 
Example #2
Source File: AbstractRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Forwards the given request to the leader if possible.
 */
protected <T extends RaftRequest, U extends RaftResponse> CompletableFuture<U> forward(T request, BiFunction<MemberId, T, CompletableFuture<U>> function) {
  CompletableFuture<U> future = new CompletableFuture<>();
  DefaultRaftMember leader = raft.getLeader();
  if (leader == null) {
    return Futures.exceptionalFuture(new RaftException.NoLeader("No leader found"));
  }

  function.apply(leader.memberId(), request).whenCompleteAsync((response, error) -> {
    if (error == null) {
      future.complete(response);
    } else {
      future.completeExceptionally(error);
    }
  }, raft.getThreadContext());
  return future;
}
 
Example #3
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Forwards the query to the leader.
 */
private CompletableFuture<QueryResponse> queryForward(QueryRequest request) {
  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(QueryResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  }

  log.trace("Forwarding {}", request);
  return forward(request, raft.getProtocol()::query)
      .exceptionally(error -> QueryResponse.builder()
          .withStatus(RaftResponse.Status.ERROR)
          .withError(RaftError.Type.NO_LEADER)
          .build())
      .thenApply(this::logResponse);
}
 
Example #4
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<MetadataResponse> onMetadata(MetadataRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(MetadataResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::metadata)
        .exceptionally(error -> MetadataResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #5
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<CommandResponse> onCommand(CommandRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(CommandResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::command)
        .exceptionally(error -> CommandResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #6
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<OpenSessionResponse> onOpenSession(OpenSessionRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(OpenSessionResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::openSession)
        .exceptionally(error -> OpenSessionResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #7
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<CloseSessionResponse> onCloseSession(CloseSessionRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(CloseSessionResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::closeSession)
        .exceptionally(error -> CloseSessionResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #8
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<JoinResponse> onJoin(JoinRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(JoinResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::join)
        .exceptionally(error -> JoinResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #9
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<ReconfigureResponse> onReconfigure(ReconfigureRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(ReconfigureResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::reconfigure)
        .exceptionally(error -> ReconfigureResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #10
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<LeaveResponse> onLeave(LeaveRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(LeaveResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::leave)
        .exceptionally(error -> LeaveResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #11
Source File: PassiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<KeepAliveResponse> onKeepAlive(KeepAliveRequest request) {
  raft.checkThread();
  logRequest(request);

  if (raft.getLeader() == null) {
    return CompletableFuture.completedFuture(logResponse(KeepAliveResponse.builder()
        .withStatus(RaftResponse.Status.ERROR)
        .withError(RaftError.Type.NO_LEADER)
        .build()));
  } else {
    return forward(request, raft.getProtocol()::keepAlive)
        .exceptionally(error -> KeepAliveResponse.builder()
            .withStatus(RaftResponse.Status.ERROR)
            .withError(RaftError.Type.NO_LEADER)
            .build())
        .thenApply(this::logResponse);
  }
}
 
Example #12
Source File: LeaderRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<AppendResponse> onAppend(final AppendRequest request) {
  raft.checkThread();
  if (updateTermAndLeader(request.term(), request.leader())) {
    CompletableFuture<AppendResponse> future = super.onAppend(request);
    raft.transition(RaftServer.Role.FOLLOWER);
    return future;
  } else if (request.term() < raft.getTerm()) {
    logRequest(request);
    return CompletableFuture.completedFuture(logResponse(AppendResponse.builder()
        .withStatus(RaftResponse.Status.OK)
        .withTerm(raft.getTerm())
        .withSucceeded(false)
        .withLastLogIndex(raft.getLogWriter().getLastIndex())
        .withLastSnapshotIndex(raft.getSnapshotStore().getCurrentSnapshotIndex())
        .build()));
  } else {
    raft.setLeader(request.leader());
    raft.transition(RaftServer.Role.FOLLOWER);
    return super.onAppend(request);
  }
}
 
Example #13
Source File: InactiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public CompletableFuture<ConfigureResponse> onConfigure(ConfigureRequest request) {
  raft.checkThread();
  logRequest(request);
  updateTermAndLeader(request.term(), request.leader());

  Configuration configuration = new Configuration(request.index(), request.term(), request.timestamp(), request.members());

  // Configure the cluster membership. This will cause this server to transition to the
  // appropriate state if its type has changed.
  raft.getCluster().configure(configuration);

  // If the configuration is already committed, commit it to disk.
  // Check against the actual cluster Configuration rather than the received configuration in
  // case the received configuration was an older configuration that was not applied.
  if (raft.getCommitIndex() >= raft.getCluster().getConfiguration().index()) {
    raft.getCluster().commit();
  }

  return CompletableFuture.completedFuture(logResponse(ConfigureResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .build()));
}
 
Example #14
Source File: RaftSessionInvokerTest.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Tests submitting a command to the cluster.
 */
@Test
public void testSubmitCommand() throws Throwable {
  RaftSessionConnection connection = mock(RaftSessionConnection.class);
  when(connection.command(any(CommandRequest.class)))
      .thenReturn(CompletableFuture.completedFuture(CommandResponse.builder()
          .withStatus(RaftResponse.Status.OK)
          .withIndex(10)
          .withResult("Hello world!".getBytes())
          .build()));

  RaftSessionState state = new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000);
  RaftSessionManager manager = mock(RaftSessionManager.class);
  ThreadContext threadContext = new TestContext();

  RaftSessionInvoker submitter = new RaftSessionInvoker(connection, mock(RaftSessionConnection.class), state, new RaftSessionSequencer(state), manager, threadContext);
  assertArrayEquals(submitter.invoke(operation(COMMAND, HeapBytes.EMPTY)).get(), "Hello world!".getBytes());
  assertEquals(1, state.getCommandRequest());
  assertEquals(1, state.getCommandResponse());
  assertEquals(10, state.getResponseIndex());
}
 
Example #15
Source File: RaftSessionInvokerTest.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Tests submitting a query to the cluster.
 */
@Test
public void testSubmitQuery() throws Throwable {
  RaftSessionConnection connection = mock(RaftSessionConnection.class);
  when(connection.query(any(QueryRequest.class)))
      .thenReturn(CompletableFuture.completedFuture(QueryResponse.builder()
          .withStatus(RaftResponse.Status.OK)
          .withIndex(10)
          .withResult("Hello world!".getBytes())
          .build()));

  RaftSessionState state = new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000);
  RaftSessionManager manager = mock(RaftSessionManager.class);
  ThreadContext threadContext = new TestContext();

  RaftSessionInvoker submitter = new RaftSessionInvoker(mock(RaftSessionConnection.class), connection, state, new RaftSessionSequencer(state), manager, threadContext);
  assertTrue(Arrays.equals(submitter.invoke(operation(QUERY)).get(), "Hello world!".getBytes()));
  assertEquals(10, state.getResponseIndex());
}
 
Example #16
Source File: RaftSessionSequencerTest.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Tests sequencing an event that arrives before a command response.
 */
@Test
public void testSequenceEventBeforeCommand() throws Throwable {
  RaftSessionSequencer sequencer = new RaftSessionSequencer(new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000));
  long sequence = sequencer.nextRequest();

  PublishRequest request = PublishRequest.builder()
      .withSession(1)
      .withEventIndex(1)
      .withPreviousIndex(0)
      .withEvents(Collections.emptyList())
      .build();

  CommandResponse response = CommandResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(2)
      .withEventIndex(1)
      .build();

  AtomicInteger run = new AtomicInteger();
  sequencer.sequenceEvent(request, () -> assertEquals(0, run.getAndIncrement()));
  sequencer.sequenceResponse(sequence, response, () -> assertEquals(1, run.getAndIncrement()));
  assertEquals(2, run.get());
}
 
Example #17
Source File: RaftSessionSequencerTest.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Tests sequencing an event that arrives before a command response.
 */
@Test
public void testSequenceEventAfterCommand() throws Throwable {
  RaftSessionSequencer sequencer = new RaftSessionSequencer(new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000));
  long sequence = sequencer.nextRequest();

  PublishRequest request = PublishRequest.builder()
      .withSession(1)
      .withEventIndex(1)
      .withPreviousIndex(0)
      .withEvents(Collections.emptyList())
      .build();

  CommandResponse response = CommandResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(2)
      .withEventIndex(1)
      .build();

  AtomicInteger run = new AtomicInteger();
  sequencer.sequenceResponse(sequence, response, () -> assertEquals(0, run.getAndIncrement()));
  sequencer.sequenceEvent(request, () -> assertEquals(1, run.getAndIncrement()));
  assertEquals(2, run.get());
}
 
Example #18
Source File: RaftSessionSequencerTest.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Tests sequencing an event that arrives before a command response.
 */
@Test
public void testSequenceEventAtCommand() throws Throwable {
  RaftSessionSequencer sequencer = new RaftSessionSequencer(new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000));
  long sequence = sequencer.nextRequest();

  PublishRequest request = PublishRequest.builder()
      .withSession(1)
      .withEventIndex(2)
      .withPreviousIndex(0)
      .withEvents(Collections.emptyList())
      .build();

  CommandResponse response = CommandResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(2)
      .withEventIndex(2)
      .build();

  AtomicInteger run = new AtomicInteger();
  sequencer.sequenceResponse(sequence, response, () -> assertEquals(1, run.getAndIncrement()));
  sequencer.sequenceEvent(request, () -> assertEquals(0, run.getAndIncrement()));
  assertEquals(2, run.get());
}
 
Example #19
Source File: RaftSessionSequencerTest.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Tests sequencing callbacks with the sequencer.
 */
@Test
public void testSequenceResponses() throws Throwable {
  RaftSessionSequencer sequencer = new RaftSessionSequencer(new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000));
  long sequence1 = sequencer.nextRequest();
  long sequence2 = sequencer.nextRequest();
  assertTrue(sequence2 == sequence1 + 1);

  CommandResponse commandResponse = CommandResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(2)
      .withEventIndex(0)
      .build();

  QueryResponse queryResponse = QueryResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(2)
      .withEventIndex(0)
      .build();

  AtomicBoolean run = new AtomicBoolean();
  sequencer.sequenceResponse(sequence2, queryResponse, () -> run.set(true));
  sequencer.sequenceResponse(sequence1, commandResponse, () -> assertFalse(run.get()));
  assertTrue(run.get());
}
 
Example #20
Source File: RaftSessionInvoker.java    From atomix with Apache License 2.0 6 votes vote down vote up
@Override
public void accept(QueryResponse response, Throwable error) {
  if (error == null) {
    if (response.status() == RaftResponse.Status.OK) {
      complete(response);
    } else if (response.error().type() == RaftError.Type.UNKNOWN_CLIENT
        || response.error().type() == RaftError.Type.UNKNOWN_SESSION) {
      complete(response.error().createException());
      state.setState(PrimitiveState.EXPIRED);
    } else if (response.error().type() == RaftError.Type.UNKNOWN_SERVICE
        || response.error().type() == RaftError.Type.CLOSED_SESSION) {
      complete(response.error().createException());
      state.setState(PrimitiveState.CLOSED);
    } else {
      complete(response.error().createException());
    }
  } else {
    fail(error);
  }
}
 
Example #21
Source File: ActiveRole.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Handles a poll request.
 */
protected PollResponse handlePoll(PollRequest request) {
  // If the request term is not as great as the current context term then don't
  // vote for the candidate. We want to vote for candidates that are at least
  // as up to date as us.
  if (request.term() < raft.getTerm()) {
    log.debug("Rejected {}: candidate's term is less than the current term", request);
    return PollResponse.builder()
        .withStatus(RaftResponse.Status.OK)
        .withTerm(raft.getTerm())
        .withAccepted(false)
        .build();
  } else if (isLogUpToDate(request.lastLogIndex(), request.lastLogTerm(), request)) {
    return PollResponse.builder()
        .withStatus(RaftResponse.Status.OK)
        .withTerm(raft.getTerm())
        .withAccepted(true)
        .build();
  } else {
    return PollResponse.builder()
        .withStatus(RaftResponse.Status.OK)
        .withTerm(raft.getTerm())
        .withAccepted(false)
        .build();
  }
}
 
Example #22
Source File: RaftSessionConnection.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Sends the given request attempt to the cluster.
 */
protected <T extends RaftRequest, U extends RaftResponse> void sendRequest(T request, BiFunction<MemberId, T, CompletableFuture<U>> sender, int count, CompletableFuture<U> future) {
  MemberId node = next();
  if (node != null) {
    log.trace("Sending {} to {}", request, node);
    int selectionId = this.selectionId;
    sender.apply(node, request).whenCompleteAsync((r, e) -> {
      if (e != null || r != null) {
        handleResponse(request, sender, count, selectionId, node, r, e, future);
      } else {
        future.complete(null);
      }
    }, context);
  } else {
    future.completeExceptionally(new ConnectException("Failed to connect to the cluster"));
  }
}
 
Example #23
Source File: DefaultRaftMetadataClient.java    From atomix with Apache License 2.0 6 votes vote down vote up
/**
 * Requests metadata from the cluster.
 *
 * @return A completable future to be completed with cluster metadata.
 */
private CompletableFuture<MetadataResponse> getMetadata() {
  CompletableFuture<MetadataResponse> future = new CompletableFuture<>();
  connection.metadata(MetadataRequest.builder().build()).whenComplete((response, error) -> {
    if (error == null) {
      if (response.status() == RaftResponse.Status.OK) {
        future.complete(response);
      } else {
        future.completeExceptionally(response.error().createException());
      }
    } else {
      future.completeExceptionally(error);
    }
  });
  return future;
}
 
Example #24
Source File: RaftSessionManager.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Handles a heartbeat request.
 */
private CompletableFuture<HeartbeatResponse> handleHeartbeat(HeartbeatRequest request) {
  log.trace("Received {}", request);
  boolean newLeader = !Objects.equals(selectorManager.leader(), request.leader());
  selectorManager.resetAll(request.leader(), request.members());
  HeartbeatResponse response = HeartbeatResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .build();
  if (newLeader) {
    resetAllIndexes();
  }
  log.trace("Sending {}", response);
  return CompletableFuture.completedFuture(response);
}
 
Example #25
Source File: RaftSessionSequencerTest.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Tests sequencing an event that arrives before a command response.
 */
@Test
public void testSequenceEventAfterAllCommands() throws Throwable {
  RaftSessionSequencer sequencer = new RaftSessionSequencer(new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000));
  long sequence = sequencer.nextRequest();

  PublishRequest request1 = PublishRequest.builder()
      .withSession(1)
      .withEventIndex(2)
      .withPreviousIndex(0)
      .withEvents(Collections.emptyList())
      .build();

  PublishRequest request2 = PublishRequest.builder()
      .withSession(1)
      .withEventIndex(3)
      .withPreviousIndex(2)
      .withEvents(Collections.emptyList())
      .build();

  CommandResponse response = CommandResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(2)
      .withEventIndex(2)
      .build();

  AtomicInteger run = new AtomicInteger();
  sequencer.sequenceEvent(request1, () -> assertEquals(0, run.getAndIncrement()));
  sequencer.sequenceEvent(request2, () -> assertEquals(2, run.getAndIncrement()));
  sequencer.sequenceResponse(sequence, response, () -> assertEquals(1, run.getAndIncrement()));
  assertEquals(3, run.get());
}
 
Example #26
Source File: RaftSessionConnection.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Handles a response from the cluster.
 */
@SuppressWarnings("unchecked")
protected <T extends RaftRequest> void handleResponse(T request, BiFunction sender, int count, int selectionId, MemberId node, RaftResponse response, Throwable error, CompletableFuture future) {
  if (error == null) {
    log.trace("Received {} from {}", response, node);
    if (COMPLETE_PREDICATE.test(response)) {
      future.complete(response);
      selector.reset();
    } else {
      retryRequest(response.error().createException(), request, sender, count + 1, selectionId, future);
    }
  } else {
    if (error instanceof CompletionException) {
      error = error.getCause();
    }
    log.debug("{} failed! Reason: {}", request, error);
    if (error instanceof SocketException || error instanceof TimeoutException || error instanceof ClosedChannelException) {
      if (count < selector.members().size() + 1) {
        retryRequest(error, request, sender, count + 1, selectionId, future);
      } else {
        future.completeExceptionally(error);
      }
    } else {
      future.completeExceptionally(error);
    }
  }
}
 
Example #27
Source File: RaftSessionInvokerTest.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Tests skipping over a failed query attempt.
 */
@Test
public void testSkippingOverFailedQuery() throws Throwable {
  CompletableFuture<QueryResponse> future1 = new CompletableFuture<>();
  CompletableFuture<QueryResponse> future2 = new CompletableFuture<>();

  RaftSessionConnection connection = mock(RaftSessionConnection.class);
  Mockito.when(connection.query(any(QueryRequest.class)))
      .thenReturn(future1)
      .thenReturn(future2);

  RaftSessionState state = new RaftSessionState("test", SessionId.from(1), UUID.randomUUID().toString(), TestPrimitiveType.instance(), 1000);
  RaftSessionManager manager = mock(RaftSessionManager.class);
  ThreadContext threadContext = new TestContext();

  RaftSessionInvoker submitter = new RaftSessionInvoker(mock(RaftSessionConnection.class), connection, state, new RaftSessionSequencer(state), manager, threadContext);

  CompletableFuture<byte[]> result1 = submitter.invoke(operation(QUERY));
  CompletableFuture<byte[]> result2 = submitter.invoke(operation(QUERY));

  assertEquals(1, state.getResponseIndex());

  assertFalse(result1.isDone());
  assertFalse(result2.isDone());

  future1.completeExceptionally(new RaftException.QueryFailure("failure"));
  future2.complete(QueryResponse.builder()
      .withStatus(RaftResponse.Status.OK)
      .withIndex(10)
      .withResult("Hello world!".getBytes())
      .build());

  assertTrue(result1.isCompletedExceptionally());
  assertTrue(result2.isDone());
  assertTrue(Arrays.equals(result2.get(), "Hello world!".getBytes()));

  assertEquals(10, state.getResponseIndex());
}
 
Example #28
Source File: RaftSessionManager.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Closes a session.
 *
 * @param sessionId the session identifier.
 * @param delete whether to delete the service
 * @return A completable future to be completed once the session is closed.
 */
public CompletableFuture<Void> closeSession(SessionId sessionId, boolean delete) {
  RaftSessionState state = sessions.get(sessionId.id());
  if (state == null) {
    return Futures.exceptionalFuture(new RaftException.UnknownSession("Unknown session: " + sessionId));
  }

  log.debug("Closing session {}", sessionId);
  CloseSessionRequest request = CloseSessionRequest.builder()
      .withSession(sessionId.id())
      .withDelete(delete)
      .build();

  CompletableFuture<Void> future = new CompletableFuture<>();
  connection.closeSession(request).whenComplete((response, error) -> {
    sessions.remove(sessionId.id());
    if (error == null) {
      if (response.status() == RaftResponse.Status.OK) {
        future.complete(null);
      } else {
        future.completeExceptionally(response.error().createException());
      }
    } else {
      future.completeExceptionally(error);
    }
  });
  return future;
}
 
Example #29
Source File: RaftSessionManager.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Resets indexes for the given session.
 *
 * @param sessionId The session for which to reset indexes.
 * @return A completable future to be completed once the session's indexes have been reset.
 */
CompletableFuture<Void> resetIndexes(SessionId sessionId) {
  RaftSessionState sessionState = sessions.get(sessionId.id());
  if (sessionState == null) {
    return Futures.exceptionalFuture(new IllegalArgumentException("Unknown session: " + sessionId));
  }

  CompletableFuture<Void> future = new CompletableFuture<>();

  KeepAliveRequest request = KeepAliveRequest.builder()
      .withSessionIds(new long[]{sessionId.id()})
      .withCommandSequences(new long[]{sessionState.getCommandResponse()})
      .withEventIndexes(new long[]{sessionState.getEventIndex()})
      .build();

  connection.keepAlive(request).whenComplete((response, error) -> {
    if (error == null) {
      if (response.status() == RaftResponse.Status.OK) {
        future.complete(null);
      } else {
        future.completeExceptionally(response.error().createException());
      }
    } else {
      future.completeExceptionally(error);
    }
  });
  return future;
}
 
Example #30
Source File: LeaderRole.java    From atomix with Apache License 2.0 5 votes vote down vote up
/**
 * Fails pending commands.
 */
private void failPendingCommands() {
  for (RaftSession session : raft.getSessions().getSessions()) {
    for (PendingCommand command : session.clearCommands()) {
      command.future().complete(logResponse(CommandResponse.builder()
          .withStatus(RaftResponse.Status.ERROR)
          .withError(RaftError.Type.COMMAND_FAILURE, "Request sequence number " + command.request().sequenceNumber() + " out of sequence")
          .withLastSequence(session.getRequestSequence())
          .build()));
    }
  }
}