Skip to content

Instantly share code, notes, and snippets.

@takei-shg
Created March 5, 2015 15:28
Show Gist options
  • Save takei-shg/b7b67e1cc52126c08049 to your computer and use it in GitHub Desktop.
Save takei-shg/b7b67e1cc52126c08049 to your computer and use it in GitHub Desktop.
com.twitter.util.Future Chain with OptionT
import scalaz._
import Scalaz._
import scalaz.OptionT._
import com.twitter.util.Future
/**
* Simple example of Future chain, which only shows type level consistency.
* Future chain can be implemented with optionT or simple flatMap chain.
*/
object Main extends App {
object JSONParser {
def read(request: Request): Option[AdRequest] = ???
}
object LocalCache {
def load(): Future[CampaignContext] = ???
}
object CampaignFilter {
def filter(request: AdRequest, ctx: CampaignContext): Option[AdResponse] = ???
}
object RedisService {
def getKey(): Future[Option[SessionKey]] = ???
}
/**
* To use optionT, necessary to make com.twitter.util.Future as instance of Monad
*/
object FutureInstances {
implicit val monadInstance = new Functor[Future] with Monad[Future] {
def point[A](a: => A): Future[A] = Future.value(a)
def bind[A, B](fa: Future[A])(f: A => Future[B]): Future[B] = fa.flatMap(f)
override def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f)
}
}
import FutureInstances._
object AdService {
val NO_CONTENT = ""
def apply(request: Request): Future[Response] = {
(for {
adReq <- optionT(JSONParser.read(request).point[Future])
ctx <- LocalCache.load().liftM[OptionT]
adRes <- optionT(CampaignFilter.filter(adReq, ctx).point[Future])
sessionKey <- optionT(RedisService.getKey())
} yield mkResponse(adRes, sessionKey)).run.map {
_.getOrElse(Response(NO_CONTENT))
}
}
/*
def apply(request: Request): Future[Response] = {
val adReqOpt: Option[AdRequest] = JSONParser.read(request)
val fAdResOpt: Future[Option[AdResponse]] = adReqOpt.map { adReq =>
val fCtx: Future[CampaignContext] = LocalCache.load()
fCtx.map { ctx =>
CampaignFilter.filter(adReq, ctx)
}
}.getOrElse {
Future.value(None)
}
fAdResOpt.flatMap { adResOpt =>
adResOpt.map { adRes =>
val fSessionKeyOpt = RedisService.getKey()
fSessionKeyOpt.flatMap { sessionKeyOpt =>
sessionKeyOpt.map { sessionKey =>
Future.value(mkResponse(adRes, sessionKey))
}.getOrElse {
Future.value(Response(NO_CONTENT))
}
}
}.getOrElse {
Future.value(Response(NO_CONTENT))
}
}
}
*/
def mkResponse(adRes: AdResponse, sessionKey: SessionKey): Response = Response(???)
}
type Request = Int
case class Response(body: String)
type AdRequest = Int
type AdResponse = Int
type CampaignContext = Int
type SessionKey = Int
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment