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

com.twitter.finagle.Deadline.scala Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
package com.twitter.finagle

import com.twitter.finagle.util.ByteArrays
import com.twitter.finagle.context.Contexts
import com.twitter.io.Buf
import com.twitter.util.{Try, Return, Throw, Time, Duration}

/**
 * A deadline is the time by which some action (e.g., a request) must
 * complete. A deadline has a timestamp in addition to the deadline.
 * This timestamp denotes the time at which the deadline was enacted.
 *
 * This is done so that they may be reconciled over process boundaries;
 * e.g., to account for variable latencies in message deliveries.
 *
 * @param timestamp the time at which the deadline was enacted.
 *
 * @param deadline the time by which the action must complete.
 */
case class Deadline(timestamp: Time, deadline: Time) extends Ordered[Deadline] {
  def compare(that: Deadline): Int = this.deadline.compare(that.deadline)
  def expired: Boolean = Time.now > deadline
  def remaining: Duration = deadline-Time.now
}

/**
 * A broadcast context for deadlines.
 */
object Deadline extends Contexts.broadcast.Key[Deadline]("com.twitter.finagle.Deadline") {

  /**
   * Returns the current request's deadline, if set.
   */
  def current: Option[Deadline] =
    Contexts.broadcast.get(Deadline)

  /**
   * Construct a deadline from a timeout.
   */
  def ofTimeout(timeout: Duration): Deadline = {
    val now = Time.now
    Deadline(now, now+timeout)
  }

  /**
   * Construct a new deadline, representing the combined deadline
   * `d1` and `d2`. Specifically, the returned deadline has the
   * earliest deadline but the latest timestamp. This represents the
   * strictest deadline and the latest observation.
   */
  def combined(d1: Deadline, d2: Deadline): Deadline =
    Deadline(d1.timestamp max d2.timestamp, d1.deadline min d2.deadline)

  def marshal(deadline: Deadline): Buf = {
    val bytes = new Array[Byte](16)
    ByteArrays.put64be(bytes, 0, deadline.timestamp.inNanoseconds)
    ByteArrays.put64be(bytes, 8, deadline.deadline.inNanoseconds)
    Buf.ByteArray.Owned(bytes)
  }

  def tryUnmarshal(body: Buf): Try[Deadline] = {
    if (body.length != 16)
      return Throw(new IllegalArgumentException(
        s"Invalid body. Length ${body.length} but required 16"))

    val bytes = Buf.ByteArray.Owned.extract(body)
    val timestamp = ByteArrays.get64be(bytes, 0)
    val deadline = ByteArrays.get64be(bytes, 8)

    Return(Deadline(Time.fromNanoseconds(timestamp), Time.fromNanoseconds(deadline)))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy