Skip to content

Instantly share code, notes, and snippets.

@reikje
Created April 26, 2016 07:29
Show Gist options
  • Save reikje/c95f9dbe34aa1af4d1904f6f99593c8f to your computer and use it in GitHub Desktop.
Save reikje/c95f9dbe34aa1af4d1904f6f99593c8f to your computer and use it in GitHub Desktop.
import java.net.SocketAddress
import com.twitter.finagle.{Addr, Name, Resolver}
import com.twitter.util.{Future, Promise, Var, Await}
import org.scalatest.{Matchers, WordSpec}
/**
* A utility trait to resolve '''destinations''' into sets of '''SocketAddress'''es.
*/
trait SocketAddressResolver {
def resolve(dest: String): Future[Set[SocketAddress]] = {
val socketAddresses = Promise[Set[SocketAddress]]()
val addresses = destResolve(dest).map { addr =>
addr.changes.filter { addrChange =>
addrChange != Addr.Pending
}.respond {
case Addr.Bound(s, _) =>
socketAddresses.setValue(s)
case Addr.Failed(t) =>
socketAddresses.setException(t)
case Addr.Neg =>
socketAddresses.setException(
throw new IllegalArgumentException(s"Destination could not be found: $dest")
)
case unknown =>
socketAddresses.setException(
throw new IllegalArgumentException(s"Unexpected Addr ($unknown) resolving: $dest")
)
}
}
addresses.getOrElse {
Future.exception(new IllegalArgumentException(s"$dest resolves to an unbound name"))
}
socketAddresses
}
private[finagle] def destResolve(dest: String): Option[Var[Addr]] = {
Resolver.eval(dest) match {
case Name.Bound(a) => Some(a)
case _ =>
None
}
}
}
class SocketAddressResolverSpec extends WordSpec with Matchers {
"SocketAddressResolver" should {
"resolve socket addresses" in {
val resolver = new FixedSocketAddressResolver(Var.value(Addr.Bound(new InetSocketAddress("0.0.0.0", 80))))
val result = Await.result(resolver.resolve("/notUsed"))
result should have size 1
}
"handle failures" in {
val resolver = new FixedSocketAddressResolver(Var.value(Addr.Failed("Something is broken")))
intercept[Exception] {
Await.result(resolver.resolve("/notUsed"))
}
}
"handle unresolvable addresses" in {
val resolver = new FixedSocketAddressResolver(Var.value(Addr.Neg))
intercept[IllegalArgumentException] {
Await.result(resolver.resolve("/notUsed"))
}
}
}
class FixedSocketAddressResolver(expected: Var[Addr]) extends SocketAddressResolver {
override private[finagle] def destResolve(dest: String): Option[Var[Addr]] = Some(expected)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment