繁体   English   中英

Iterable 的未来顺序运行

[英]Future of Iterable to run sequentially

带解释的代码:

val partitions = preparePartitioningDataset(dataset, "sdp_id").map { partitions =>
  val resultPartitionedDataset: Iterator[Future[Iterable[String]]] = for {
    partition <- partitions
  } yield {
    val whereStatement = s"SDP_ID = '$partition'"
    val partitionedDataset =
      datasetService.getFullDatasetResultIterable(
        dataset = dataset,
        format = format._1,
        limit = none[Int],
        where = whereStatement.some
      )
    partitionedDataset
  }
  
  resultPartitionedDataset
}

partitions.map { partitionedDataset =>
  for {
    partition <- partitionedDataset
  } notifyPartitionedDataset(
    bearerToken = bearerToken,
    endpoint = endpoint,
    dataset = partition
  )
}

所以现在

  • preparePartitioningDataset(dataset, "sdp_id")返回一个Future[Iterator[String]]
  • datasetService.getFullDatasetResultIterable自身也返回一个Future[Iterable[String]]
  • 你几乎看到resultPartitionedDataset是一个Iterator[Future[Iterable[String]]]
  • 最后notifyPartitionedDataset返回一个Future[Unit]

关于正在发生的事情和我正在努力实现的一些解释

我有preparePartioningDataset ,它对单个值执行Select Distinct ,返回 Future[ResultSet] (映射到迭代器)。 这是因为对于每个单个值,我想执行SELECT * WHERE column=that_value 这发生在getFullDatasetResultIterable上,同样是 Future[ResultSet] 映射到迭代器。

最后一步是通过 POST 转发我收到的每一个查询。 它可以工作,但一切都是并行发生的(好吧,我想这就是为什么我想要 go 作为未来的原因),但现在我需要每个 POST( notifyPartionedDataset )按顺序发生,所以要一个接一个地发送一个帖子,而不是并行发送。

我尝试了很多不同的方法,但我仍然得到相同的结果。

我怎么能往前走?

您可以利用IO数据类型的惰性来确保某些操作按顺序执行。

import cats.effect.IO

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def preparePartitioningDatasetIO(dataset: String, foo: String): IO[List[String]] =
  IO.fromFuture(IO(
    preparePartitioningDataset(dataset, foo))
  )).map(_.toList)

def getFullDatasetResultIterableIO(dataset: String, format: String, limit: Option[Int], where: Option[String]): IO[List[String]] =
  IO.fromFuture(IO(
    datasetService.getFullDatasetResultIterable(
      dataset,
      format,
      limit,
      where
    )
  ))
  
def notifyPartitionedDatasetIO(bearerToken: String, endpoint: String, dataset: List[String]): IO[Unit] =
  IO.fromFuture(IO(
    notifyPartitionedDataset(
      bearerToken,
      endpoint,
      dataset
    )
  ))
  
def program(dataset: String): IO[Unit] =
  preparePartitioningDatasetIO(dataset, "sdp_id").flatMap { partitions =>
    partitions.traverse_ { partition =>
      val whereStatement = s"SDP_ID = '$partition'"
      getFullDatasetResultIterableIO(
        dataset = dataset,
        format = format._1,
        limit = none,
        where = whereStatement.some
      ).flatMap { dataset =>
        notifyPartitionedDatasetIO(
          bearerToken = bearerToken,
          endpoint = endpoint,
          dataset = dataset
        )
      }
    }
  }


def run(dataset: String): Future[Unit] = {
  import cats.effect.unsafe.implicits.global
  program(dataset).unsafeToFuture()
}

代码需要仔细审查和修复,尤其是函数的arguments。
但是,这应该有助于获得您想要的结果,而无需重构整个代码库; 然而。


如果您希望getFullDatasetResultIterableIO并行运行而notifyPartitionedDatasetIO串行运行,您可以这样做:

def program(dataset: String): IO[Unit] =
  preparePartitioningDatasetIO(dataset, "sdp_id").flatMap { partitions =>
    partitions.parTraverse { partition =>
      val whereStatement = s"SDP_ID = '$partition'"
      getFullDatasetResultIterableIO(
        dataset = dataset,
        format = format._1,
        limit = none,
        where = whereStatement.some
      )
    } flatMap { datasets =>
      datasets.traverse_ { dataset =>
        notifyPartitionedDatasetIO(
          bearerToken = bearerToken,
          endpoint = endpoint,
          dataset = dataset
        )
      }
    }
  }

虽然这意味着在开始通知之前整个数据都保存在 memory 中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM