簡體   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