Параллельный запуск запросов в 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
Я попробовал следующее:
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
Тем не менее, экземпляр NonEmptyParallel не найден для ConnectionIO
,
Ошибка:(107, 54) не удалось найти неявное значение для параметра p: cats.NonEmptyParallel[doobie.ConnectionIO,F] val result = (program(i1),program(i2)). ParMapN{case (a,b) => a ++ b}
Я упускаю что-то очевидное или пытаюсь сделать что-то, что невозможно Спасибо
0 ответов
Вы не можете запускать запросы в
ConnectionIO
монада параллельно. Но как только вы превратите их в вашу фактическую монаду времени выполнения (если у нее есть экземпляр Parallel), вы сможете.
Например, с монадой среды выполнения ввода-вывода cats-effect:
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
Включите свой
ConnectionIO
в
IO
val program1IO: IO[List[(String, BigDecimal)]]] = program(i1).transact(xa)
val program2IO: IO[List[(String, BigDecimal)]]] = program(i2).transact(xa)
Теперь у вас есть монада, которая может делать что-то параллельно.
val result: IO[List[(String, BigDecimal)]]] =
(program1IO, program2IO).parMapN{case (a,b) => a ++ b}
Чтобы понять почему
ConnectionIO
не позволяет делать что-то параллельно, я просто процитирую tpolecat:
Вы не можете запустить ConnectionIO параллельно. Это язык, описывающий использование соединения, которое представляет собой линейную последовательность операций.
Используя parMapN в IO, да, вы можете запускать две вещи одновременно, потому что они работают в разных соединениях.
Нет parMapN с ConnectionIO, потому что у него нет (и не может) быть экземпляра Parallel.