9

I use Finagle as a web server which I want to return Scala-Futures from my application logic. How to convert scala.concurrent.Future to com.twitter.util.Future, in a non-blocking way of course?

jans
  • 1,768
  • 3
  • 17
  • 22

3 Answers3

21

Have not enough environment to test this, but here is what i write for "com.twitter" %% "finagle-http" % "6.25.0":

import com.twitter.{util => twitter}
import scala.concurrent.{ExecutionContext, Promise, Future}
import scala.util.{Failure, Success, Try}
import language.implicitConversions

object TwitterConverters {
  implicit def scalaToTwitterTry[T](t: Try[T]): twitter.Try[T] = t match {
    case Success(r) => twitter.Return(r)
    case Failure(ex) => twitter.Throw(ex)
  }

  implicit def twitterToScalaTry[T](t: twitter.Try[T]): Try[T] = t match {
    case twitter.Return(r) => Success(r)
    case twitter.Throw(ex) => Failure(ex)
  }

  implicit def scalaToTwitterFuture[T](f: Future[T])(implicit ec: ExecutionContext): twitter.Future[T] = {
    val promise = twitter.Promise[T]()
    f.onComplete(promise update _)
    promise
  }

  implicit def twitterToScalaFuture[T](f: twitter.Future[T]): Future[T] = {
    val promise = Promise[T]()
    f.respond(promise complete _)
    promise.future
  }
}
Odomontois
  • 15,918
  • 2
  • 36
  • 71
  • I can confirm this is still working with Finagle 6.33.0. Thanks, @Odomontois. – marcospereira Feb 26 '16 at 16:03
  • This only wraps the result of a scala future in a twitter future. So anything you invoke on the returned future (such as cancel) won't have an effect. – rethab Jun 16 '16 at 11:24
15

It's also possible to use Twitter bijections library: https://github.com/twitter/bijection

Namely com.twitter.bijection.twitter_util.UtilBijections (https://github.com/twitter/bijection/blob/develop/bijection-util/src/main/scala/com/twitter/bijection/twitter_util/UtilBijections.scala)

This library handles important details, for example if you convert object forth and back, it just unwraps original object.

Wildfire
  • 6,358
  • 2
  • 34
  • 50
8

Here's an example using the twitter bijection library:

import scala.concurrent.{Future => ScalaFuture}
import com.twitter.util.{Future => TwitterFuture}

// extend values by adding the conversion method "as"
import com.twitter.bijection.Conversion.asMethod

// pull in various implicit converters that "as" expects, 
// including twitter2ScalaFuture:
import com.twitter.bijection.twitter_util.UtilBijections._

def doSomething: ScalaFuture[T] = {
    val response: TwitterFuture[T] = ???
    response.as[ScalaFuture[T]]
}
mikebridge
  • 4,209
  • 2
  • 40
  • 50
  • 1
    I also needed to import an ExecutionContext `import scala.concurrent.ExecutionContext.Implicits.global` – suicide Jan 29 '18 at 15:16