2016-02-29 4 views
1

Рассмотрите модель для выбора Master/Slave для кластера.Scala Совокупный результат от нескольких вызовов Future

Member{ id: Long, isMaster: Boolean } 

У меня есть Дао/Repo со следующими методами:

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

В MemberService, я пытаюсь написать функцию, чтобы установить isMaster ложь для всех существующих членов, и я в конечном итоге с этим бешено раздутый код:

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. Как должно быть написано оператор возврата для обработки успеха/ошибки? например При успешном возврате Future (true) и on failure, return Future (false) 2. Является ли этот способ повторного отображения будущего правильным способом выполнения асинхронного программирования в scala? Я понимаю, что это может быть написано по-разному в парадигме актера и, вероятно, намного лучше, но в случае ООП это лучшая скала?

Спасибо.

ответ

2

Почему вы делаете MemberDao.findById, когда вы уже держите член в руке ??? (Вы также относитесь к возврату как к члену, в то время как он действительно должен быть Option [Member]). Кроме того, обновление не обязательно должно принимать идентификатор в качестве отдельного параметра (имеется один доступный внутри member). Вам не нужно вызывать Await, потому что ваша функция возвращает Future, и вам не нужно возвращать Boolean: просто выбросьте исключение из-за сбоя сигнала. Рассмотрим что-то вроде этого:

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

Не все, что раздутый, это? :)

+0

Делает большой смысл, очевидно, начинающий разработчик scala здесь, еще один вопрос, memberDao.update принимает члена, а не Будущего [Member], и это то, что возвращает memberDao.all. Итак, я предполагаю, что мне нужно еще сделать отображение memberFuture =>? – BZapper

+0

Нет, в вашем определении '.all' возвращает' Future [List [Member]] '. Первая «.flatMap» в моем фрагменте выглядит внутри «Будущего», а затем «foreach» выполняет итерацию через список «Пользователь». Обратите внимание, что я обновил ответ, чтобы исправить несовместимость возвращаемого типа: вам нужна 'Future.sequence' внутри' .flatMap', чтобы преобразовать список фьючерсов в будущий список, а затем '.map' в конце отбрасывает список, чтобы сделать результат 'Future [Unit]', а не 'Future [List [Unit]]' – Dima

Смежные вопросы