Исходный код akka сам по себе является хорошим советом, что нужно делать. Посмотрите akka.pattern.PipeToSupport
:
def pipeTo(recipient: ActorRef)(implicit sender: ActorRef = Actor.noSender): Future[T] = {
future andThen {
case Success(r) ⇒ recipient ! r
case Failure(f) ⇒ recipient ! Status.Failure(f)
}
}
Таким образом, мы можем в основном повторно использовать этот подход для нашего случая с диспетчеризацией Either
:
val result: Future[Either[Int, Throwable]] = Future.successful(Left(5))
result andThen {
case Success(Left(value)) => leftActor ! value
case Success(Right(exception)) => rightActor ! exception
case Failure(exception) => println("Failure")
}
Достижения желаемого DSL:
Мы можем попытаться достичь ваш DSL (orPipe() и to (...)) примерно:
trait MyEitherPipeSupport extends PipeToSupport {
final class PipeableEitherFuture[L, R](val future: Future[Either[L, R]])(implicit executionContext: ExecutionContext) {
def to(leftRef: ActorRef, rightRef: ActorRef, exceptionRef: ActorRef) = future andThen {
case Success(Left(value)) ⇒ leftRef ! value
case Success(Right(exception)) ⇒ rightRef ! exception
case Failure(exception) ⇒ exceptionRef ! Status.Failure(exception)
}
}
implicit def eitherPipe[L, R](future: Future[Either[L, R]])(implicit executionContext: ExecutionContext): PipeableEitherFuture[L, R] = new PipeableEitherFuture(future)
}
Теперь в вашем актера вы просто смешать MyEitherPipeSupport
и вы можете написать так:
val result: Future[Either[Int, Throwable]] = Future.successful(Left(5))
eitherPipe(result).to(left, right, anotherOne)
Есть ли что-нибудь еще вы хотели бы видеть в ответ на этот вопрос? – tkachuko