Skip to content

Commit 2573789

Browse files
matil019seratch
andauthored
Add Txboundary example for Cats Effect (#98)
* Fix the double evaluation in myIOTxBoundary.finishTx Applies the suggestions in scalikejdbc/scalikejdbc#1105 * Make myIOTxBoundary.closeConnection exception-safe It really should be, because the `result` is actually the execution (contents of localTx) itself plus finishTx. * Fix a deprecated syntax scalac-2.13.3 complains it * Remove the extraneous type parameter I believe the A refers to the `type A`, not the param `[A]`. * Add Cats Effect IO example * Apply rewording suggestions from code review Co-authored-by: Kazuhiro Sera <[email protected]> * Apply formatting suggestions from code review Co-authored-by: Kazuhiro Sera <[email protected]> * Remove leading `#` of the titles * Revert title changes Co-authored-by: Kazuhiro Sera <[email protected]>
1 parent 9aa8019 commit 2573789

File tree

1 file changed

+64
-11
lines changed

1 file changed

+64
-11
lines changed

source/documentation/transaction.html.md

+64-11
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,14 @@ val fResult = DB localTx { implicit s =>
133133
```
134134

135135
<hr/>
136-
### #Working with IO monads
136+
### Working with IO monads
137137
<hr/>
138138

139-
*MyIO (IO monads minimal example)*
139+
<hr/>
140+
#### IO monad minimal example
141+
<hr/>
140142

143+
*MyIO*
141144

142145
```scala
143146
sealed abstract class MyIO[+A] {
@@ -167,7 +170,7 @@ sealed abstract class MyIO[+A] {
167170
}
168171

169172
object MyIO {
170-
def apply[A](a: => A): MyIO[A] = Delay(a _)
173+
def apply[A](a: => A): MyIO[A] = Delay(() => a)
171174

172175
final case class Delay[+A](thunk: () => A) extends MyIO[A]
173176
}
@@ -183,16 +186,17 @@ implicit def myIOTxBoundary[A]: TxBoundary[MyIO[A]] = new TxBoundary[MyIO[A]] {
183186

184187
def finishTx(result: MyIO[A], tx: Tx): MyIO[A] = {
185188
result.attempt.flatMap {
186-
case Right(_) => MyIO(tx.commit()).flatMap(_ => result)
187-
case Left(_) => MyIO(tx.rollback()).flatMap(_ => result)
189+
case Right(a) => MyIO(tx.commit()).flatMap(_ => MyIO(a))
190+
case Left(e) => MyIO(tx.rollback()).flatMap(_ => MyIO(throw e))
188191
}
189192
}
190193

191194
override def closeConnection(result: MyIO[A], doClose: () => Unit): MyIO[A] = {
192195
for {
193-
x <- result
194-
_ <- MyIO(doClose).map(x => x.apply())
195-
} yield x
196+
x <- result.attempt
197+
_ <- MyIO(doClose())
198+
a <- MyIO(x.fold(throw _, identity))
199+
} yield a
196200
}
197201
}
198202
```
@@ -208,7 +212,7 @@ import scalikejdbc._
208212

209213
type A = ???
210214

211-
def asyncExecution[A]: DBSession => MyIO[A] = ???
215+
def asyncExecution: DBSession => MyIO[A] = ???
212216

213217
// default
214218
DB.localTx(asyncExecution)(boundary = myIOTxBoundary)
@@ -218,6 +222,57 @@ NamedDB('named).localTx(asyncExecution)(boundary = myIOTxBoundary)
218222

219223
```
220224

225+
226+
<hr/>
227+
#### Cats Effect IO example
228+
<hr/>
229+
230+
*TxBoundary typeclass instance for cats.effect.IO[A]*
231+
232+
`cats.effect.IO` offers two ways to handle completion/cancellation as below. You can use `guaranteeCase` for commit/rollback operations while going with `guarantee` for connection closure.
233+
234+
```scala
235+
import scalikejdbc._
236+
import cats.effect._
237+
238+
implicit def catsEffectIOTxBoundary[A]: TxBoundary[IO[A]] = new TxBoundary[IO[A]] {
239+
def finishTx(result: IO[A], tx: Tx): IO[A] =
240+
result.guaranteeCase {
241+
case ExitCase.Completed => IO(tx.commit())
242+
case _ => IO(tx.rollback())
243+
}
244+
245+
override def closeConnection(result: IO[A], doClose: () => Unit): IO[A] =
246+
result.guarantee(IO(doClose()))
247+
}
248+
```
249+
250+
251+
*localTx*
252+
253+
To take control of all the side-effects that happen in `localTx` method, you can use `suspend` method to wrap the code blocks using `localTx`.
254+
255+
```scala
256+
import scalikejdbc._
257+
import cats.effect._
258+
259+
type A = ???
260+
261+
def ioExecution: DBSession => IO[A] = ???
262+
263+
// default
264+
IO.suspend {
265+
DB.localTx(ioExecution)(boundary = catsEffectIOTxBoundary)
266+
}
267+
268+
// named
269+
IO.suspend {
270+
NamedDB('named).localTx(ioExecution)(boundary = catsEffectIOTxBoundary)
271+
}
272+
273+
```
274+
275+
221276
<hr/>
222277
### #withinTx block / session
223278
<hr/>
@@ -245,5 +300,3 @@ try {
245300
db.rollbackIfActive() // it NEVER throws Exception
246301
} finally { db.close() }
247302
```
248-
249-

0 commit comments

Comments
 (0)