When the timeout expires, however, the Future's body code keeps running even if the TimeoutException has been raised. As an example, run this code in a Scala REPL:
We might still be trying to start them in a separate thread.
This PR introduces timeout parameters in DockerCommandExecutor methods which propagates down to the implementations of this interface. There, it replaces Future.apply factory invocation with PerishableFuture.apply. It also adds PerishableFuture factory which makes sure the body gets interrupted when the timeout expires:
case finiteTimeout: FiniteDuration =>
val promise = Promise[T]
val futureTask = new FutureTask[T](new Callable[T] {
override def call(): T = body
}) {
override def done(): Unit = promise.tryComplete {
Try(get()).recoverWith {
case _: CancellationException => Failure(new TimeoutException())
}
}
}
val reaperTask = new TimerTask {
override def run(): Unit = {
futureTask.cancel(true)
promise.tryFailure(new TimeoutException())
}
}
timer.schedule(reaperTask, finiteTimeout.toMillis)
ec.execute(futureTask)
promise.future
If the passed timeout is Duration.Inf it just doesn't timeout so it uses standard Future factory:
case _ => Future.apply(body)
These changes should improve host resources usage and pave the way to more advanced timeouts customization.
Currently,
PullImagesTimeout
,StartContainersTimeout
, andStopContainersTimeout
timeouts are enforced byAwait.ready
,Await.result
, ... e.g:https://github.com/whisklabs/docker-it-scala/blob/4d3bc7e8630fcdb7bc1a51a11a49f543564b38a4/core/src/main/scala/com/whisk/docker/DockerKit.scala#L57-L60
When the timeout expires, however, the
Future
'sbody
code keeps running even if theTimeoutException
has been raised. As an example, run this code in a Scala REPL:The result is that the exception is raised and yet "BOOM" is printed:
This means that, as we try to stop the containers in
afterAll
:https://github.com/whisklabs/docker-it-scala/blob/4d3bc7e8630fcdb7bc1a51a11a49f543564b38a4/scalatest/src/main/scala/com/whisk/docker/scalatest/DockerTestKit.scala#L24-L28
We might still be trying to start them in a separate thread.
This PR introduces
timeout
parameters inDockerCommandExecutor
methods which propagates down to the implementations of this interface. There, it replacesFuture.apply
factory invocation withPerishableFuture.apply
. It also addsPerishableFuture
factory which makes sure thebody
gets interrupted when the timeout expires:If the passed timeout is
Duration.Inf
it just doesn't timeout so it uses standardFuture
factory:These changes should improve host resources usage and pave the way to more advanced timeouts customization.