简体   繁体   中英

Mutate implicit "Context" parameter

I have application that build on akka-http and slick. All services works with slick DBIO instances which transforms into Future in the routes classes. Implicit parameter widely used through services to pass context about current request (user id, permissions etc.) Typical methods signature looks in following way:

def getProject(id: ProjectId)(implicit context: Context): DBIO[Project] = {???}

Everything was fine until this context was readonly. Now I have a requirement to implement domain events approach and dispatch events only after transaction commit. So I decided to store list of events in context and fire them after successfully transforming DBIO into Future .

My question is how properly mutate this implicit context through different service methods in functional way? I thought about using State monad transformer , but it feels that it bring more complexity cause all services already build over DBIO .

If you consider using Cats Effect, you could use Ref to store events.

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 ...

Then before running transaction:

for { 
  result <- ... // your queries, where you pass events 
  eventList <- events.get
} yield (result, eventList)

Ref acts like an atomic wrapper around some data and uses effect defined by you to provide some safety.

There are other options:

  • ignoring referential transparency and just passing mutable data structure
  • using some monad transformer like StateT or WriterT

What you pick is a matter of preference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM