Last active
August 29, 2015 14:03
-
-
Save j5ik2o/37a09ccaea7e02860eeb to your computer and use it in GitHub Desktop.
spray-routingをベースしたControllerの書き方
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import akka.actor._ | |
import akka.io.IO | |
import spray.can.Http | |
import spray.routing.{Directives, HttpService, RequestContext, Route} | |
trait Action { | |
def apply(request: RequestContext): Unit | |
} | |
object Action { | |
def apply(block: RequestContext => Unit) = new Action { | |
override def apply(ctx: RequestContext): Unit = block(ctx) | |
} | |
} | |
trait ControllerSupport extends Directives { | |
protected def getQueryParam(key: String)(implicit ctx: RequestContext): Option[String] = | |
ctx.request.uri.query.get(key) | |
} | |
// ほんとはこのアプリケーションサービス内でドメインモデルとファクトリ、リポジトリが登場するが、サンプルなので省略している。 | |
case class FactApplicationService { | |
def fact(n: Seq[Long]): Seq[Future[Long]] = { | |
Future.traversal(n) { n => | |
fact(n) | |
} | |
} | |
private def fact(n: Long): Long = { | |
def fact0(result: Long, n: Long): Long = | |
n match { | |
case 0 => result | |
case _ => fact0(n * result, n - 1) | |
} | |
fact(1, n) | |
} | |
} | |
case class FactController(factApplicationService: FactApplicationService) extends ControllerSupport { | |
def fact = Action { implicit ctx => | |
val values: Seq[Int] = getQueryParam("values") | |
.map(s => s.split(",") | |
.map(_.toInt).toSeq) | |
.getOrElse((1 to 10).toSeq) | |
val future: Future[Seq[Int]] = | |
Future.sequence(factApplicationService.fact(values)) | |
val results: Seq[Int] = Await.result(future, Duration.Inf) | |
ctx.complete(s"results = $results") | |
} | |
} | |
trait Routes extends HttpService with ControllerSupport { | |
val factController = FactController() | |
protected val routes: Route = { | |
get { | |
path("fact") { ctx => | |
factController.fact(ctx) | |
} | |
} | |
} | |
} | |
class ServiceActor extends Actor with Routes { | |
def actorRefFactory = context | |
def receive = runRoute(routes) | |
} | |
object Main extends App { | |
implicit val system = ActorSystem() | |
val handler = system.actorOf(Props[ServiceActor], name = "handler") | |
IO(Http) ! Http.Bind(handler, interface = "localhost", port = 8080) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment