Scala Aggregate来自多个Future调用

时间:2016-02-29 21:43:41

标签: scala concurrency playframework future

考虑一个群集的主/从选举模型。

Member{ id: Long, isMaster: Boolean } 

我有以下方法的Dao / Repo:

MemberDao.findById(id:Long):Future[Option[Member]]
MemberDao.update(id:Long, member: Member):Future[Unit]
MemberDao.all() : Future[List[Member]]

在MemberService中,我试图编写一个函数来为所有现有成员将isMaster设置为false,并且我最终得到了这个疯狂膨胀的代码:

class MemberService ... {
  def demoteAllMembers() : Future[Boolean] = {
    val futures = memberDao.all.map{ memberFuture =>
      memberFuture.map{ member =>
        memberDao.findById(member.id).map { existingMemberFuture =>
          existingMemberFuture.map { existingMember =>
            memberDao.update(existingMember.id, existingMember.copy(isMaster = false)
          }
        }
      }
      val results = Await.result(futures, 10 seconds)

      // return something here
    }
  }


}

我的问题是: 1.如何编写return语句来处理成功/错误?例如成功后,返回Future(true)并在失败时返回Future(false) 2.这种重复映射未来在scala中进行异步编程的正确方法吗?我理解这可以在Actor范例中以不同的方式编写,可能要好得多,但是在OOP的情况下,这是最好的Scala可以做到的吗?

感谢。

1 个答案:

答案 0 :(得分:2)

当你手里拿着一个成员时,你为什么要成员D.dind.findById? (您也将会员作为会员处理,而它应该是一个选项[会员])。 此外,更新不需要将id作为单独的参数(member内有一个可用)。 您不需要Await您的结果,因为您的函数返回Future,并且您不需要返回Boolean:只需抛出异常即可信号失败。 考虑这样的事情:

def demoteAllMembers: Future[Unit] = memberDao.all.flatMap { 
   Future.sequence(_.foreach {
     memberDao.update(_.copy(isMaster = false))
   })
 }.map ( _ => () ) 

不是那么臃肿,是吗? :)