在 Slick 事务中做自己的东西

Do own stuff in Slick transaction

我正在使用 Slick 3.1.1,我想在 Slick 事务上实现我自己的东西。

def findSomeProducts = table.getSomeProducts() //db operation
def productTableUpdate = doSomeStuff1() //db operation
def priceTableUpdate = doSomeStuff2() //db operation

def updateElasticCache = updateIndexOfProduct() //this is not a database operation

我有这些示例函数。首先,我从 db 获取了一些产品,然后更新了表格。最后我需要 运行 updateElasticCache 方法。如果 updateElasticCache 方法失败,我想回滚整个数据库过程。

我不会用 (for { ... } yield ()).transactionally 此代码因为它不适用于我的案例。此 'transactionally' 正在等待数据库操作。但我想添加另一个不是数据库进程的功能。

可能吗?我怎样才能实现它?

DBIO.from

是的!!!可以使用 DBIO 操作组合和 DBIO.from

在光滑的数据库逻辑之间添加非数据库逻辑

注意 "your own stuff" 应该 return 一个 future,future 可以转换为 DBIO 并且可以与通常的数据库操作一起组合。

DBIO.from 可以帮助您解决这个问题。下面是它的工作原理。 DBIO.from 获取未来并将其转换为 DBIOAction。现在您可以将这些操作与常用的数据库操作组合起来,以在事务中执行非数据库操作和数据库操作。

def updateElasticCache: Future[Unit] = Future(doSomething())

现在假设我们有一些数据库操作

def createUser(user: User): DBIO[Int] = ???

如果更新缓存失败,我希望 createUser 回滚。所以我做了以下

val action = createUser.flatMap { _ => DBIO.from(updateElasticCache()) }.transactionally
db.run(action)

现在,如果 updateElasticCache 失败,整个 tx 将失败,一切都会回滚到正常状态。

例子

你可以用for comprehension让它好看

def updateStats: DBIO[Int] = ???
val rollbackActions =
  (for {
     cStatus <- createUser()
     uStatus <- updateStats()
     result <- DBIO.from(updateElasticCache())
   } yield result).transactionally
 db.run(rollbackActions)

如果 updateElasticCache 未来失败,一切都会回滚