public synchronized ListenableFuture<?> waitForMinimumCoordinatorSidecars()
    {
        if (currentCoordinatorSidecarCount == 1 || !isCoordinatorSidecarEnabled) {
            return immediateFuture(null);
        }

        SettableFuture<?> future = SettableFuture.create();
        coordinatorSidecarSizeFutures.add(future);

        // if future does not finish in wait period, complete with an exception
        ScheduledFuture<?> timeoutTask = executor.schedule(
                () -> {
                    synchronized (this) {
                        future.setException(new PrestoException(
                                NO_CPP_SIDECARS,
                                format("Insufficient active coordinator sidecar nodes. Waited %s for at least 1 coordinator sidecars, but only 0 coordinator sidecars are active", coordinatorSidecarMaxWait)));
                    }
                },
                coordinatorSidecarMaxWait.toMillis(),
                MILLISECONDS);

        // remove future if finished (e.g., canceled, timed out)
        future.addListener(() -> {
            timeoutTask.cancel(true);
            removeCoordinatorSidecarFuture(future);
        }, executor);

        return future;
    }
@Test(timeOut = 60_000)
    public void testWaitForMinimumCoordinatorSidecars()
            throws InterruptedException
    {
        ListenableFuture<?> coordinatorSidecarsFuture = waitForMinimumCoordinatorSidecars();
        assertFalse(monitor.hasRequiredCoordinatorSidecars());
        assertFalse(coordinatorSidecarsTimeout.get());
        assertEquals(minCoordinatorSidecarsLatch.getCount(), 1);
        addCoordinatorSidecar(nodeManager);
        minCoordinatorSidecarsLatch.await(1, SECONDS);
        assertTrue(coordinatorSidecarsFuture.isDone());
        assertFalse(coordinatorSidecarsTimeout.get());
        assertTrue(monitor.hasRequiredCoordinatorSidecars());
    }