All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gfccollective.concurrent.Timeouts.scala Maven / Gradle / Ivy

The newest version!
package org.gfccollective.concurrent

import java.util.concurrent.{TimeoutException, Executors}

import scala.concurrent.{Promise, Future}
import scala.concurrent.duration.FiniteDuration

/**
 * Factory module to build timing out Futures.
 *
 * @author [email protected]
 * @since 22-Nov-2014
 */
object Timeouts {
  import JavaConverters._
  private[concurrent] val scheduledExecutor = Executors.newSingleThreadScheduledExecutor().asScala

  /**
   * Returns a timing out Future.
   *
   * A failing Future is returned that will throw a TimeoutException after the given expiration time.
   *
   * @param after a FiniteDuration instance with the ttl of this Future.
   */
  def timeout[T](after: FiniteDuration): Future[T] = timeout(after, None)

  /**
   * Returns a timing out Future.
   *
   * A failing Future is returned that will throw a TimeoutException after the given expiration time.
   *
   * @param after a FiniteDuration instance with the ttl of this Future.
   * @param errorMessage Error message that will be used to construct any resultant TimeoutException
   */
  def timeout[T](after: FiniteDuration, errorMessage: Option[String]): Future[T] = scheduleTimeout(after, errorMessage)

  // TODO unclear if an HashedWheelTimer would be more efficient
  private def scheduleTimeout[T](after: FiniteDuration, errorMessage: Option[String]): Future[T] = {
    val timingOut = Promise()
    val now = System.currentTimeMillis()
    val origin = errorMessage.fold(new TimeoutException())(new TimeoutException(_))

    scheduledExecutor.schedule(after) {
      val elapsed = System.currentTimeMillis() - now
      timingOut.tryFailure(origin.initCause(new TimeoutException(s"""Timeout after ${after} (real: ${elapsed} ms.)""")))
    }

    timingOut.future
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy