FailureDetector implements Heartbeater.Callback, Closeable { public boolean isAvailable() { Long failureTimestamp = lastFailureTimestampMillis.get(); if (failureTimestamp != null) { if (failureTimestamp > System.currentTimeMillis() - config.getFailureIntervalMillis()) { return false; } else { lastFailureTimestampMillis.set(null); } } return failureDetectStrategy.isAvailable(); } FailureDetector(FailureDetectStrategy failureDetectStrategy, Heartbeater heartbeater, Config config);  FailureDetector(FailureDetectStrategy failureDetectStrategy, Heartbeater heartbeater); @Override void onHeartbeat(); @Override void onFailure(Throwable cause); boolean isAvailable(); @Override void close(); FailureDetectStrategy getFailureDetectStrategy(); Heartbeater getHeartbeater(); int getFailureIntervalMillis(); @Override String toString();  }
@Test void testIsAvailable() throws IOException, InterruptedException { final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(null); int localPort = serverSocketChannel.socket().getLocalPort(); final ExecutorService executorService = Executors.newSingleThreadExecutor(); Runnable serverTask = () -> { while (!executorService.isShutdown()) { try (SocketChannel accept = serverSocketChannel.accept()) { LOG.debug("Accepted: {}", accept); } catch (IOException e) { LOG.warn("Stab TCP server got an error", e); } } try { serverSocketChannel.close(); } catch (IOException e) { LOG.warn("Failed to close serverSocketChannel", e); } }; executorService.execute(serverTask); TCPHeartbeater.Config heartbeaterConfig = new TCPHeartbeater.Config(); heartbeaterConfig.setPort(localPort); PhiAccrualFailureDetectStrategy.Config failureDetectorConfig = new PhiAccrualFailureDetectStrategy.Config(); try (FailureDetector failureDetector = new FailureDetector( new PhiAccrualFailureDetectStrategy(failureDetectorConfig), new TCPHeartbeater(heartbeaterConfig))) { assertTrue(failureDetector.isAvailable()); TimeUnit.SECONDS.sleep(4); assertTrue(failureDetector.isAvailable()); executorService.shutdownNow(); for (int i = 0; i < 20; i++) { if (!failureDetector.isAvailable()) { break; } TimeUnit.MILLISECONDS.sleep(500); } assertFalse(failureDetector.isAvailable()); } }