Подождите х миллисекунд или пока условие не станет истинным - PullRequest
1 голос
/ 21 февраля 2020

У меня есть код, в который я отправляю данные в наши очереди, а затем из очереди отправляю подтверждение обратно о том, что они получили данные, поэтому я жду X времени, прежде чем проверять, получили ли они данные или нет. Ниже приведен код, который делает это и работает:

  public boolean send(final long address, final byte[] records, final Socket socket) {
    boolean sent = sendAsync(address, records, socket, true);
    if (sent) {
      try {
        TimeUnit.MILLISECONDS.sleep(800);
      } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
      }
    }
    // if key is not present, then acknowledgement was received successfully
    sent = !acknowledgementCache.asMap().containsKey(address);
    // and key is still present in the cache, then it means acknowledgment was not received after
    // waiting for timeout period, so we will remove it from cache.
    if (!sent)
      removeFromRetryBucket(address);
    return sent;
  }

Теперь проблема с приведенным выше кодом - я жду 800 milliseconds независимо от того, что и что не так. Вполне возможно, что подтверждение вернулось через 100 миллисекунд, но я все еще жду 800, поэтому я хочу вернуться, как только пришло подтверждение, вместо того, чтобы ждать это количество X времени.

Итак, я пришел с кодом ниже, который использует awaitility , но по какой-то причине он работает не так, как ожидалось. То есть, несмотря на то, что подтверждение вернулось быстро, оно все равно истекло. Я также попытался увеличить значение тайм-аута до очень большого числа, но время ожидания истекло, поэтому что-то не так. Есть ли лучший способ сделать это?

  public boolean send(final long address, final byte[] records, final Socket socket) {
    boolean sent = sendAsync(address, records, socket, true);
    if (sent) {
      try {
        // if key is not present, then acknowledgement was received successfully
        Awaitility.await().atMost(800, TimeUnit.MILLISECONDS)
            .untilTrue(new AtomicBoolean(!acknowledgementCache.asMap().containsKey(address)));
        return true;
      } catch (ConditionTimeoutException ex) {
      }
    }
    // and key is still present in the cache, then it means acknowledgment was not received after
    // waiting for timeout period, so we will remove it from cache.
    removeFromRetryBucket(address);
    return false;
  }

Примечание: Я работаю с Java 7 на данный момент. У меня есть доступ к Гуаве, так что если есть что-то лучшее, кроме ожидания, тогда я тоже могу это использовать.

1 Ответ

2 голосов
/ 21 февраля 2020

Чтобы иметь возможность проверить, что в Java 7 вам нужно написать вызываемый объект.

@Test
public void send() {
    //when
    boolean sent = sendAsync(address, records, socket, true);
    //then
    if (sent) {
        await().until(receivedPackageCount(), equalTo(false));
    }
}

private Callable receivedPackageCount(String address) {
    return new Callable() {
        @Override
        public boolean call() throws Exception {
            return acknowledgementCache.asMap().containsKey(address);
        }
    };
}

Это должно быть что-то похожее выше. Могут быть ошибки компиляции, потому что я написал это без ide.

...