在Doobie中并行运行查询

mdm*_*mdm 6 functional-programming scala scala-cats doobie

是否可以使用Doobie并行运行多个查询?

我有以下(伪)查询:

def prepareForQuery(input: String): ConnectionIO[Unit] = ???
val gettAllResults: ConnectionIO[List[(String, BigDecimal)]] = ???
def program(input : String) : ConnectionIO[List[(String, BigDecimal)]] = for{
    _ <- prepareForQuery(input)
    r <- gettAllResults
  } yield r
Run Code Online (Sandbox Code Playgroud)

我尝试了以下内容:

import doobie._
import doobie.implicits._
import cats.implicits._
val xa = Transactor.fromDataSource[IO](myDataSource)
val result = (program(i1),program(i2)).parMapN{case (a,b) => a ++ b}
val rs = result.transact(xa).unsafeRunSync
Run Code Online (Sandbox Code Playgroud)

但是,找不到的NonEmptyParallel实例ConnectionIO

错误:(107,54)找不到参数p的隐式值:cats.NonEmptyParallel [doobie.ConnectionIO,F] val结果=(program(i1),program(i2))。parMapN {case(a,b)= > a ++ b}

我是否缺少明显的东西或尝试无法完成的事情?谢谢

soo*_*ote 5

您不能在ConnectionIOmonad 中并行运行查询。但是一旦你把它们变成你实际的运行时 monad(只要它有一个 Parallel 实例),你就可以。

例如,使用cats-effect IO 运行时monad:

def prepareForQuery(input: String): ConnectionIO[Unit] = ???
val gettAllResults: ConnectionIO[List[(String, BigDecimal)]] = ???
def program(input : String) : ConnectionIO[List[(String, BigDecimal)]] = for{
    _ <- prepareForQuery(input)
    r <- gettAllResults
  } yield r
Run Code Online (Sandbox Code Playgroud)

把你ConnectionIO变成一个IO

val program1IO: IO[List[(String, BigDecimal)]]] = program(i1).transact(xa)
val program2IO: IO[List[(String, BigDecimal)]]] = program(i2).transact(xa)
Run Code Online (Sandbox Code Playgroud)

你现在有一个可以并行处理的 monad。

val result: IO[List[(String, BigDecimal)]]] = 
    (program1IO, program2IO).parMapN{case (a,b) => a ++ b}
Run Code Online (Sandbox Code Playgroud)

要了解为什么ConnectionIO不允许您并行执行操作,我将引用 tpolecat:

您不能并行运行 ConnectionIO。它是一种描述连接使用的语言,连​​接是线性操作序列。

在 IO 中使用 parMapN,是的,您可以同时运行两件事,因为它们在不同的连接上运行。

ConnectionIO 没有 parMapN,因为它没有(也不能)有一个 Parallel 实例。