scala - 变异隐式“上下文”参数
问题描述
我有基于 akka-http 和 slick 的应用程序。DBIO
所有服务都与转换为Future
路由类的光滑实例一起工作。通过服务广泛使用的隐式参数来传递有关当前请求的上下文(用户 ID、权限等)。典型的方法签名如下所示:
def getProject(id: ProjectId)(implicit context: Context): DBIO[Project] = {???}
一切都很好,直到这个上下文是只读的。现在我需要实现域事件方法并仅在事务提交后调度事件。所以我决定将事件列表存储在上下文中,并在成功转换DBIO
为Future
.
我的问题是如何通过不同的服务方法以功能方式正确地改变这个隐式上下文?我考虑过使用State monad 转换器,但感觉它带来了更多复杂性,因为所有服务都已经构建完毕DBIO
。
解决方案
如果您考虑使用 Cats Effect,则可以使用 Ref 来存储事件。
val events: F[Ref[F, List[DomainEvent]]] = Ref.of[F, List[DomainEvent]](Nil)
// assuming that you'll make F=DBIO and provide necessary type class instances
def getProject(id: ProjectId)(implicit events: Ref[DBIO, List[DomainEvents]]): DBIO[Project] = for {
... // database actions
_ <- events.update(list :+ event)
} yield ...
然后在运行事务之前:
for {
result <- ... // your queries, where you pass events
eventList <- events.get
} yield (result, eventList)
Ref 就像一些数据的原子包装器,并使用您定义的效果来提供一些安全性。
还有其他选择:
- 忽略引用透明度,只传递可变数据结构
- 使用像 StateT 或 WriterT 这样的 monad 转换器
你选择什么是一个偏好问题。
推荐阅读
- kivy - 为什么 kivy 在与 python 的“elevate()”函数一起使用时会失败?
- python - Pandas,获取 pct 变化周期均值
- python - 如何在 django 中传递多个可选的 URL 参数?
- spring-boot - Spring Boot 应用程序休息调用在 tomcat 中为下一个请求提供 404 错误
- c# - WPF-为什么我的项目中的 keyDown 功能不起作用?
- python - 如何计算通过unittest调用了内部类方法的次数?
- firebase - 群聊与 Flutter 和 Firebase
- faunadb - FaunaDB 按日期范围获取条目,索引绑定不起作用
- azure - 在我的工作区中获取仪表板时,Power BI API 返回 403 被禁止
- jquery - 如何将无序列表的最后一个元素输出到控制台?