Skip to content

Instantly share code, notes, and snippets.

@aboisvert
Created February 17, 2025 01:49
Show Gist options
  • Save aboisvert/c716c9e08f6d91c2b427fd855e3b4645 to your computer and use it in GitHub Desktop.
Save aboisvert/c716c9e08f6d91c2b427fd855e3b4645 to your computer and use it in GitHub Desktop.
Illustration of using Scala macro to statically prevent nested transactions using the scalasql library
// See https://github.com/com-lihaoyi/scalasql
import scalasql.*
/** Shorthand for delimited transaction:
*
* ```
* db.txn:
* val data = runSomeQuery()
* doSomeUpdate(...)
* ```
*/
extension (db: DbClient)
/** Runs `f` as part of a database transaction */
inline def txn[T](f: DbApi.Txn ?=> T): T =
TxnMacros.txnImpl(db, f)
object TxnMacros:
import scala.quoted.*
import scala.compiletime.{error, summonFrom}
def txnImpl[T](db: Expr[DbClient], f: Expr[DbApi.Txn ?=> T])(using _quotes: Quotes, _typeT: Type[T]): Expr[T] =
'{
checkNoNestedTransaction()
$db.transaction(txn => $f(using txn))
}
inline def checkNoNestedTransaction(): Unit =
summonFrom[DbApi.Txn]:
case _: DbApi.Txn => error("Nested transactions not supported")
case _ => ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment