我正在与Akka Streams合作并尝试使用Flow
阶段来最有效地描述整个图表。在某些阶段,我通过ask
模式向演员发送消息。
当然,当我使用ask
模式时,我需要使用mapTo
才能获得预期的类型以便进一步处理。
以下是一个例子:
val runnableGraph = Source.single(CheckEntity(entity))
.map { check =>
(postgresActor ? check)
.mapTo[CheckEntityResult]
.map {
case failure: PostgresFailure => Left(failure.message)
case pEntity: PEntity => Right(check)
}
}
.map {
_.map {
case Left(msg) => Future(Left(msg))
case Right(check) =>
(redisActor ? pEntity)
.mapTo[CheckEntityResult]
.map {
case failure: RedisFailure => Left(failure.message)
case rEntity: REntity => Right(rEntity)
}
}
}
.toMat(Sink.head)(Keep.right)
//The result's type is Future[Future[Either[String, Entity]]]
val futureResult = runnableGraph.run()
如何摆脱各阶段之间的嵌套Future
?
答案 0 :(得分:2)
通过流传播CheckEntity
元素更容易的一个想法是更改CheckEntityResult
类以包含相应的CheckEntity
实例。这看起来像这样:
abstract class CheckEntityResult(entity: CheckEntity) extends Entity
case class PEntity(entity: CheckEntity) extends CheckEntityResult(entity)
case class PostgresFailure(entity: CheckEntity, message: String) extends CheckEntityResult(entity)
case class REntity(entity: CheckEntity) extends CheckEntityResult(entity)
case class RedisFailure(entity: CheckEntity, message: String) extends CheckEntityResult(entity)
然后,在调整actor以处理这些消息之后,您可以使用Source # ask
和mapAsync
(根据需要调整并行度级别)与actor进行交互并避免嵌套{{1在物化值中:
Future
答案 1 :(得分:1)
您可以考虑将您的actor查询转换为Flow
以及mapAsync
(具有适当的并行性):
val postgresCheck = (check: CheckEntity) =>
(postgresActor ? check).mapTo[CheckEntityResult]
.map {
case failure: PostgresFailure => Left(failure.message)
case pEntity: PEntity => Right(check)
}
val redisCheck = (e: Either[String, CheckEntityResult]) => e match {
case Left(msg) => Future(Left(msg))
case Right(checkResult) =>
(redisActor ? checkResult).mapTo[CheckEntityResult]
.map {
case failure: RedisFailure => Left(failure.message)
case rEntity: REntity => Right(rEntity)
}
}
val postgresCheckFlow = (parallelism: Int) =>
Flow[CheckEntity]
.mapAsync[Either[String, CheckEntityResult]](parallelism)(postgresCheck)
val redisCheckFlow = (parallelism: Int) =>
Flow[Either[String, CheckEntityResult]]
.mapAsync[Either[String, CheckEntityResult]](parallelism)(redisCheck)
使用转换后的流程,您的runnableGraph可以如下组合,结果类型为Future[Either[]]
:
val runnableGraph = Source.single(CheckEntity(entity))
.via(postgresCheckFlow(parallelism))
.via(redisCheckFlow(parallelism))
...