Ответ 1
@Viktor Klang: Мы понимаем, что j.u.c.Future
является мерзостью. Но то, что мы получаем от части программного обеспечения, мы должны принять, как указано на данный момент.
До сих пор это то, что мы взломали вместе:
def wrapJavaFutureInAkkaFuture[T](javaFuture: java.util.concurrent.Future[T], maybeTimeout: Option[Duration] = None)(implicit system: ActorSystem): akka.dispatch.Future[T] = {
val promise = new akka.dispatch.DefaultPromise[T]
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout.map(_.fromNow))
promise
}
Другими словами, создайте отдельный Akka Promise
(сторона записи Future
), соответствующая j.u.c.Future
, отменит обратный вызов pollJavaFutureUntilDoneOrCancelled
, чтобы обновить Promise, опросив "мерзость", и возвращает обещание вызывающему абоненту.
Итак, как мы можем "опросить", чтобы обновить обещание Akka на основе состояния j.u.c.Future?
def pollJavaFutureUntilDoneOrCancelled[T](javaFuture: java.util.concurrent.Future[T], promise: akka.dispatch.Promise[T], maybeDeadline: Option[Deadline] = None)(implicit system: ActorSystem) {
if (maybeDeadline.exists(_.isOverdue)) javaFuture.cancel(true);
if (javaFuture.isDone || javaFuture.isCancelled) {
promise.complete(allCatch either { javaFuture.get })
} else {
Play.maybeApplication.foreach { implicit app =>
system.scheduler.scheduleOnce(50 milliseconds) {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeDeadline)
}
}
}
}
Это попытка того, что было намечено в обсуждении групп google, на которое я ссылался в вопросе. Он использует планировщик Akka для вызова себя каждые 50 мс, чтобы проверить, что j.u.c.Future либо выполнен, либо отменен. Всякий раз, когда это происходит, он обновляет обещание Akka с завершенным состоянием.
@Victor Klang и др.:
Это лучшая практика? Вы знаете лучший способ сделать это? Не хватает ли здесь недостатка, о котором мы должны знать?
Спасибо за дополнительную помощь.