Functional Programming Patterns for the Asynchronous Web

NEScala happened this year, and it was amazing! Not only was I able to give a talk, we were also able to record a scalawags podcast.

For those who missed the talk, it was about how to script together a bunch of asynchronous APIs into a new asynchronous APIs. SO, generically, we have:

trait AsynchSubService {
  def getData: Future[Data]
}
trait AsynchSubService2 {
  def getData: Future[Data2]
}

What you want to do is create a new service that can call both asynchronously and non-blocking so that we don't suck up too many threads waiting for IO (or network response).

trait UberAsynchService {
  def getData: Future[(Data, Data2)]
}

SO, how do I accomplish this across a variety of goals? The example application is one that checks github statistics to see which projects are more likely to accept pull requests from non-committers.

Here's the example application. It implements the same github statistics service in two ways:

You'll notice that the code to implement the Future-only version is almost exactly the same as the "generic" version. There's a bit of difference in supporting code, but most of that is just an implementation of scalaz.

What is different is the testing strategies. The future-based code has to use "Await" for a result, which in my experience usually leads to flaky tests in some manner or other, while the abstracted service can implement single-threaded tests.

SO, the gain of all that abstraction is the ability to substitute different runtime execution models into our business logic. Regardless of whether or not you find the gain worth the cost, the underlying patterns of joining and sequencing computations are useful for anyone delving into Scala's Future library.

Here's a copy of the slides, and I beleive a video will be posted shortly.

Comments

blog comments powered by Disqus