Scala等待过期的Future没有看到TimeoutException

时间:2016-01-24 09:40:01

标签: scala apache-kafka

我正在尝试将Kafka的回调制作人发送 API作为未来。即:

def sendFuture[K, V](p: KafkaProducer[K, V], rec: ProducerRecord[K, V]): Future[RecordMetadata] = {
  val promise = Promise[RecordMetadata]()
  p.send(rec, new Callback {
    override def onCompletion(metadata: RecordMetadata, exception: Exception): Unit = {
      if (metadata != null) {
        promise.complete(Success(metadata))
      } else {
        promise.complete(Failure(exception))
      }
    }
  })
  promise.future
}

我故意禁用Kafka代理,以便生产者在配置的时间(5000毫秒)内保持连接。
在我的测试中,我只等待2秒,并期望看到 TimeoutException 被抛出。

"a producer can't connect to the broker, we " should {
  "see timeout when sending messages" in withProducer { p: KafkaProducer[String, String] =>
    val rec = new ProducerRecord[String, String](TEST_TOPIC, "testKey", "testValue")
    val f = sendFuture(p, rec)

    log.info(">> sent and we wait for at most 1 second...")
    intercept[TimeoutException] {
      Await.ready(f, 2 seconds)
    }
    log.info(">> TimeoutException intercepted")
  }
}

我希望Await等待“ on parallel ”,然后触发 TimeoutException 。 不幸的是,我的测试会失败。 似乎等待,尽管有2秒的界限,但总是等到未来完成发送的回调失败。 我不太明白原因。

我认为这更多地与Kafka的实现细节有关 当Kafka 发送回调完成Future时,我才会观察到这种行为。 也就是说,将sendFuture替换为dummyFuture会通过测试:

def dummyFuture(): Future[Boolean] = {

  val promise = Promise[Boolean]()
  val thread = new Thread(new Runnable {
    override def run(): Unit = {
      Thread.sleep(5000)
      promise.complete(Success(true))
    }
  })
  thread.start()
  promise.future
}

感谢您的帮助。

Gist

Kafka Producer API

1 个答案:

答案 0 :(得分:0)

我发现我错误地认为send在它仍在尝试连接时立即返回。 Await不会超时,因为它在 send达到配置的超时后启动,并在失败时完成了未来。