В настоящее время моей целью является взаимодействие с БД с использованием подхода CRUD.Между простой операцией у меня могут быть некоторые дополнительные шаги (дополнительная бизнес-логика, которая может вызвать некоторые ошибки).
import cats.effect.IO
import scalikejdbc._
IO(NamedDB(MyDB) localTx {
implicit session => {
val x = for {
a <- IO(select()) // Option[Something] (1)
_ <- IO(log(a)) // Option[Something] (2)
_ <- IO(insert()) // Something (3)
_ <- IO(insert()) // Something (4)
c <- IO(select()) // Option[Something] (5)
r <- IO(fileSystemOperation(a, c)) // (6)
_ <- operation(r) // Either[Throwable, Unit] (7)
} yield ()
x.unsafeRunSync() // (8)
}
}).attempt.unsafeRunSync() match { // (9)
case Left(value) => println("Error")
case Right(value) => println("Success") // in reality i want to return some result here
}
Первая проблема возникает (2)
: я получил ошибку:
Несоответствие типа ошибки;найдено: cats.effect.IO [Unit] требуется: опция [?] _ <- IO (log (a)) </p>
Но если я записываю результат любой вставки ((3)
или * 1012)*) тогда все ок.Возможно, это из-за разницы в типе результата Option[Something]
против Something
, но я подумал, что это будет так же, как это:
for {
a <- Option(1)
....
}
Второй вопрос - как правильно обрабатывать ошибки в (7)
откатить транзакцию?Должен ли я использовать сопоставление с образцом и сделать что-то вроде этого:
operation(r) match {
case Left(e) => throw e
}
, или я могу выдать ошибку внутри моего operation
и вернуть Unit
вместо Either[Throwable, Unit]
?
Также, у меня есть вопрос о (8)
и (9)
.Это правильный способ начать фактическую обработку и обработать любую ошибку или нет?
Я попытался сделать те же шаги, используя этот подход:
select() match {
case Some(_) =>
.....
operation(r) match {
case Left(e) => throw e
case Right(_) => ....
}
case None => ....
}
Но в результате я получил слишком глубоко match-case
статей, и это было трудно читать и понимать.Я новичок в FP, но я хочу реализовать это в FP.