Akka:回复对Actor的回复

时间:2015-12-30 15:08:02

标签: scala akka slick

我有以下代码将响应发送回发送方Actor(响应的actor使用Slick从表中加载列表):

class ManageUsersData extends Actor {

  def receive = {
    case _       => {
      sender ! loadUsers
    }
  }


  def loadUsers =  {

    var list = new ListBuffer[String]()
    val db = Database.forConfig("dbconfig")
    try {

      val users: TableQuery[Users] = TableQuery[Users]
      val future = db.run(users.result)


      future onComplete {
        case Success(u) => u.foreach {
          user => {
            list += user.firstName
          }
          list
        }
        case Failure(t) => println("An error has occured: " + t.getMessage)
      }

    } finally db.close

   list

  }
}

这里的问题是loadUsers在等待Future完成之前返回。怎么能接近这个?

3 个答案:

答案 0 :(得分:3)

您应该使用pipe pattern

import akka.pattern.pipe

// ...

def receive = {
  val originalSender = sender
  loadUsers pipeTo originalSender
}

答案 1 :(得分:3)

Jean Logeart已经提到了概念解决方案。关于loadUsers,我认为这是一个较短的版本?

def loadUsers =  {

    val db = Database.forConfig("dbconfig")
    try {

      val users: TableQuery[Users] = TableQuery[Users]
      db.run(users.result).map(_.firstName)

    } catch {
      case e: Exception => println("An error has occured: " + e.getMessage)
    } finally db.close

 }

答案 2 :(得分:2)

我认为,最简单的方法是将future发送回sender,而不是 async-filled list

  def loadUsers =  {

    val db = Database.forConfig("dbconfig")
    try {

      val users: TableQuery[Users] = TableQuery[Users]

      val future = db.run(users.result)

      future.map {     //the future
        _.map {        //the returning Seq
          _.firstName 
        }
      }

    } finally db.close

  }

现在调用者角色有处理未来或失败的负担。

这也有一个缺点,如果sender使用ask / ?操作,异步结果将是Future包裹Future pipeTo }。

您可以使用sender方法解决此问题,该方法会向调用方发送未来消息,而无需打扰解包它。

管道的缺点结果是firstName应该有办法识别哪个回复属于哪个请求。一种可能的解决方案是发送一个请求标识符,该标识符将与答案一起发回,因此请求的演员可以轻松链接这两个。

旁注

为什么要在未来结果中映射 let dataManager = DataManager.getGolfCoursesFromFileWithSuccess { (data) -> Void in let json = JSON(data: data) if let courseArray = json.array { for course in courseArray { let golfCourseName: String? = course["biz_name"].string let city: String? = course["e_city"].string let state: String? = course["e_state"].string if golfCourseName != nil { let course = Course() course.name = golfCourseName! course.city = city! course.state = state! let realm = try! Realm() try! realm.write { realm.add(course) } } } } } 属性而不是在光滑查询中使用投影?我认为这是为了保持示例的简单。