Michael
Michael

Reputation: 42100

Synchronous and Asynchronous client code in Scala

This is a follow-up to my old question. Suppose I need to invoke a REST service both synchronously and asynchronously. In the synchronous case I would like to do it on the caller thread without taking other threads from the pool.

I would like to write my business logic only once and reuse it in the both cases. The business logic consists of building a request and handling the response.

I would like also to compose REST invocations, as if in "invoke service A and then service B and then service C"

How would you do it in Scala ?

Upvotes: 3

Views: 342

Answers (1)

Rich Henry
Rich Henry

Reputation: 1849

This should run in the current thread...

{
  val currentThreadEx = new AbstractExecutorService {
    override def execute(r: Runnable) { r.run }
    override def shutdownNow(): java.util.List[Runnable] = new java.util.ArrayList[Runnable]()
    override def shutdown() {}
    override def isTerminated = false
    override def isShutdown = false
    override def awaitTermination(timeout: Long, unit: TimeUnit) = false
  }
  implicit val exContext = ExecutionContext.fromExecutor(currentThreadEx)

  val f = Future {
    10 + 1
  } 

  println(Await.result(f, 1 seconds))
}

This will run on the default executor...

{
  import ExecutionContext.Implicits.global

  val f = Future {
    10 + 1
  } 

  println(Await.result(f, 1 seconds))
}

As you can see, you can use ExecutorService as the abstraction point.

Or you can use a function written in terms of Monads, and then you can bind those operations together without dealing with the context (i.e. Future).

  def op1[M[_]: Monad](i: Int)(j: Int): M[Int] = {
    Monad[M].point { i * j }
  }

  println(Monad[Id].point(10) >>= op1[Id](10))
  println((Future { 10 } >>= op1[Future](10)).run)

Upvotes: 2

Related Questions