简体   繁体   中英

Akka HTTP + actor + slick postgresql

I am re-learning Scala, and I wanted to do a system flow as follows

Routes(Akka-Http) which asks an Actor Model(Akka) which then asks the Database through a Slick Model.

Something like

Route

path("rooms"){
  get {
    val rooms = (actorRoom ? GetRooms).mapTo[Seq[Room]] //bad code
    complete(rooms) //bad code
  }
}

ActorRoom

def receive = {
  case GetRooms => sender() ! ModelRoom.getRooms()

Slick Model

val rooms = TableQuery[RoomTable]
def getRooms(): Future[Seq[Room]] = rooms.result

My problem is that i am not sure when to resolve the rooms.

Should I do it within the actor? (the route complete does not seem to wait)

Should I do it within the route? (how should i do it?)

Is this approach correct, or the actor is too much?

Adding an Actor in the flow when your DB call itself is asynchronous can be dangerous since it can lead to un-predictable results.

But if you ignore all the unpredictability and still want to do it, you can make it work like this,

your route,

import akka.pattern.ask
import akka.actor.Status
import scala.util.{Success, Failure}

path("rooms"){
  get {
    val dbCallThroughActor = (actorRoom ? GetRooms).map({
      case Status.Success(seq) => seq
      case Status.Failure(ex) => throw ex
    })
    onComplete(dbCallThroughActor.mapTo[Seq[Room]]) {
      case Success(seq) => complete(seq)
      // or your can reject with your rejection handler
      case Failure(ex) => complete(ex)
    }
  }
}

your actor,

import context.dispatcher

def receive = {
  case GetRooms =>
    ModelRoom.getRooms().pipeTo(sender())
}

your slick model,

val rooms = TableQuery[RoomTable]
def getRooms()(implicit ec: ExecutionContext): Future[Seq[Room]] = database.run(rooms.result)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM