17

Doobie bookによると、リポジトリ レイヤーから ConnectionIO を返すことをお勧めします。これにより、呼び出しをチェーンして 1 つのトランザクションで実行することができます。素晴らしくクリア。

ここで、REST API サービスに取り組んでおり、シナリオが次のようになっているとします。

  1. データベースでオブジェクトを見つける
  2. このオブジェクトで (cats.effect.IO または monix.eval.Task を使用して) 非同期操作を実行します。
  3. オブジェクトをデータベースに格納します。

そして、これらすべてのステップを 1 つのトランザクション内で実行したいと考えています。問題は、 によって与えられる自然な変換がなければ、transactor.trans()2 つのモナド内で作業していることです -TaskConnectionIO. それは可能ではありません。

ConnectionIO問題は、1つのトランザクションで作業していて、世界の終わりにすべてのDBミューテーションをコミット/ロールバックできるように、1つのコンポジションでdoobieとエフェクトモナドをどのように混在させるかです?

ありがとうございました!

UPD:小さな例

def getObject: ConnectionIO[Request]                      = ???
def saveObject(obj: Request): ConnectionIO[Request]       = ???
def processObject(obj: Request): monix.eval.Task[Request] = ???

val transaction:??? = for {
    obj       <- getObject             //ConnectionIO[Request]
    processed <- processObject(obj)    //monix.eval.Task[Request]
    updated   <- saveObject(processed) //ConnectionIO[Request]
  } yield updated

UPD2: @oleg-pyzhcov が提供する正しい答えは、効果のデータ型をConnectionIO次のように持ち上げることです。

def getObject: ConnectionIO[Request]                      = ???
def saveObject(obj: Request): ConnectionIO[Request]       = ???
def processObject(obj: Request): monix.eval.Task[Request] = ???

val transaction: ConnectionIO[Request] = for {
    obj       <- getObject                                           //ConnectionIO[Request]
    processed <- Async[ConnectionIO].liftIO(processObject(obj).toIO) //ConnectionIO[Request]
    updated   <- saveObject(processed)                               //ConnectionIO[Request]
} yield updated
val result: Task[Request] = transaction.transact(xa)
4

1 に答える 1

18

ConnectionIOin doobieにはcats.effect.Asyncinstanceがあり、とりわけ、メソッドを使用して anyを変換cats.effect.IOできます。ConnectionIOliftIO

import doobie.free.connection._
import cats.effect.{IO, Async}
val catsIO: IO[String] = ???
val cio: ConnectionIO[String] = Async[ConnectionIO].liftIO(catsIO)

の場合monix.eval.Task、最善の策Task#toIOは同じトリックを使用して実行することですが、スコープ内に monix が必要ですScheduler

于 2018-05-23T06:26:17.260 に答える