簡體   English   中英

Slick run 方法返回的 Future 在插入行之前成功完成

[英]Future returned by Slick run method completes successfully before rows have been inserted

我正在使用 Slick 和 PostgreSQL 進行存儲的 Scala 應用程序。 我有一個方法foo從一個 CSV 文件中讀取數據並將大約 10,000 行插入到數據庫中。 在行插入操作的 Future 完成后,另一個方法bar被調用,它從數據庫中檢索這些行並對它們執行一些操作。 這就是問題所在:實際上沒有從數據庫中檢索行,因為在 Future 完成時沒有插入任何行。

從我在尋找答案和官方文檔時可以收集到的信息來看,在成功執行插入語句之前,未來不應該完成。 如果我將以下代碼Thread.sleep(30000)bar ,允許首先執行 insert 語句,則這些方法會提供預期的結果。 現在,出於顯而易見的原因,我寧願不這樣做,所以我正在尋找替代方案。

下圖說明了調用初始方法doStuff的程序流程:

The program flow diagram

doStuff在返回 Future 之前調用foo加載數據並將其存儲在數據庫中。 然后在doStuff映射此 Future 並調用bar bar bar 從數據庫中檢索行並處理它們。 但是,由於在調用bar的位置沒有插入任何行,因此不會處理任何數據。

doStuff方法:

def doStuff(csvFile: File): Future[Unit] = {
  fooService.foo(csvFile)
    .map(_ => {
      csvFile.delete()
      barService.bar()
    })
}

foo方法:

def foo(file: File) Future[Unit] = {
  val reader = CSVReader.open(file)
  fooStorage.truncateFooData().map(_ => {
    val foos = for (line <- reader.iterator if
    line.head != "bad1" &&
      line.head !="bad2")
      yield parseFooData(line)
    fooStorage.saveFooDataBulk(foos.toSeq)
  })
}

我如何使用 Slick 插入行:

override def saveFooDataBulk(fooSeq: Seq[Foo]): Future[Seq[Foo]] =
  db.run(DBIO.seq(fooQuery ++= fooSeq)).map(_ => fooSeq)

我希望在所有行都插入數據庫后調用bar ,而不是更早,但是,目前 Slick 的 Future 完成得太快了。 如果相關:當請求發送到 Akka Http 端點時,將調用doStuff方法。 應用程序和數據庫在兩個不同的 docker 容器中運行。 我究竟做錯了什么?

此外,我無法忘記我一年半前選擇的用戶名現在有多合適。

def fooflatMap替換map 否則,它將啟動一個Future[Seq[Foo]] ,然后立即返回一個() ,然后被您的doStuff丟棄。 像這樣的東西:

fooStorage
  .truncateFooData()
  .flatMap(_ => {
    /* stuff... */
    fooStorage.saveFooDataBulk(foo.toSeq)
  })
  .map(_ => ())

我沒有測試它,但無論如何,在另一個Future.map中間啟動一些Future ,然后立即返回一個()感覺不太正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM