「AkkaFutureでjava.util.concurrent.Futureをラップするにはどうすればよいですか?」で説明されているように、Akkaポーラーを実行することになったので、@Hbfによる回答を解決策としてマークしています。。参考までに、私も試しました:
- HystrixCommandExcutionHookを作成し、HystrixCommandを拡張してコールバックを許可します。フックが適切なタイミングで呼び出されなかったため、これは機能しませんでした。
- 装飾されたエグゼキュータにHystrix内に先物を作成させ、コマンドから先物をキャストすることにより、Guavasのリッスン可能な先物を使用します。Hystrixは装飾できないThreadPoolExecutorを使用しているため、機能しません。
編集:元の答えはScalaにあり、Javaの将来がうまくキャンセルされない場合はハングするため、以下にAkkaポーラーコードを追加しています。以下の解決策は、タイムアウト後に常にスレッドから離れます。
protected Future wrapJavaFutureInAkkaFuture(final java.util.concurrent.Future javaFuture, final Option maybeTimeout, final ActorSystem actorSystem) {
final Promise promise = Futures.promise();
if (maybeTimeout.isDefined()) {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option.option(maybeTimeout.get().fromNow()), actorSystem);
} else {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option. none(), actorSystem);
}
return promise.future();
}
protected void pollJavaFutureUntilDoneOrCancelled(final java.util.concurrent.Future javaFuture, final Promise promise, final Option maybeTimeout, final ActorSystem actorSystem) {
if (maybeTimeout.isDefined() && maybeTimeout.get().isOverdue()) {
// on timeouts, try to cancel the Java future and simply walk away
javaFuture.cancel(true);
promise.failure(new ExecutionException(new TimeoutException("Future timed out after " + maybeTimeout.get())));
} else if (javaFuture.isDone()) {
try {
promise.success(javaFuture.get());
} catch (final Exception e) {
promise.failure(e);
}
} else {
actorSystem.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), new Runnable() {
@Override
public void run() {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout, actorSystem);
}
}, actorSystem.dispatcher());
}
}