The Settable implementation in RAFT is not friendly to the StateMachine when current thread is interrupted
When calling setAsync in leader node, the RAFT will be called directly by current thread, because there is a BlockingQueue.put operation in the process, that make the process interruptible, and the InterruptedException is not thrown out, instead return a CompletableFuture that never be completed. It only happens on leader node but not followers since there is no interruptible operations in followers. I think either making the setAsync uninterruptible or throwing out the InterruptedException are both OK, that makes the StateMachine easier to control its methods are interruptible or not.
Makes sense to me. I would return a CompletableFuture.failedFuture(exception) instead of adding a checked exception. The internal queue is something I had in mind to re-work in the future when time is available. So I wouldn't expose the exception for callers.
How about use non-blocking interface instead, the failure result returns immediately if there is no space, that make a consistent result for both leader and follower nodes, and avoid to handle a uncontrolled interrupted status of external thread.
if (!processing_queue.offer(request)) {
retval.completeExceptionally(new IllegalStateException("processing queue is full"));
return retval;
}
Unfortunately, we can't do that right now. The processing queue is shared for user requests and RAFT messages. This means we could drop internal messages without retrying. We have plans to split the queue in the future. Issue #168 also gives some more details on other issues.
The simplest change (for now) is to complete the operation if the put request fails.