Skip to content

Instantly share code, notes, and snippets.

@agleyzer
Last active December 27, 2015 17:39
Show Gist options
  • Save agleyzer/7363353 to your computer and use it in GitHub Desktop.
Save agleyzer/7363353 to your computer and use it in GitHub Desktop.
import com.twitter.conversions.time._
import com.twitter.finagle.{Addr, Name}
import com.twitter.finagle.util.DefaultTimer
import com.twitter.logging.Logger
import com.twitter.util.{Duration, Future, FuturePool, Timer, Updatable, Var}
import java.net.{InetAddress, InetSocketAddress, SocketAddress}
import java.security.Security
/**
* A name that continuously resolves itself with DNS.
*/
private[util] trait DnsBackedName extends Name {
private[this] val log = Logger(this.getClass)
private[this] val addrVar = Var[Addr](Addr.Pending)
protected def host: String
protected def ttl: Duration
protected def timer: Timer
protected def resolveHost: Future[Set[SocketAddress]]
override val bind = addrVar
protected[util] def loop(currentSet: Set[SocketAddress] = Set.empty): Unit = {
resolveHost handle { case ex =>
log.error("failed to resolve host: " + ex)
addrVar() = Addr.Failed(ex)
Set[SocketAddress]()
} onSuccess { newSet =>
if (currentSet != newSet) {
log.debug("%s is now: %s", host, newSet.mkString(", "))
addrVar() = Addr.Bound(newSet.toSeq:_*)
}
timer.doLater(ttl) { loop(newSet) }
}
}
}
private[util] class BlockingDnsBackedName(val host: String, val port: Int,
val ttl: Duration, val timer: Timer) extends DnsBackedName {
private[this] def blockingDnsCall: Set[SocketAddress] =
InetAddress.getAllByName(host).map { address =>
new InetSocketAddress(address, port): SocketAddress
}.toSet
protected def resolveHost: Future[Set[SocketAddress]] =
FuturePool.unboundedPool(blockingDnsCall)
loop()
}
object DnsBackedName {
def apply(host: String, port: Int, ttl: Duration): Name =
new BlockingDnsBackedName(host, port, ttl, DefaultTimer.twitter)
def apply(host: String, port: Int): Name = {
// TTL using Java standard secutity property
val ttl = {
val minTtl = 5.seconds
val defaultTtl = 10.seconds
val maxTtl = 1.hour
val property = Option(Security.getProperty("networkaddress.cache.ttl"))
property map (_.toInt.seconds max minTtl min maxTtl) getOrElse defaultTtl
}
apply(host, port, ttl)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment