DiazCarrete,
@DiazCarrete@hachyderm.io avatar

When building Servant applications with persistence, a common (?) pattern is to request a database connection from a pool in the callback we pass to "hoistServer" https://hackage.haskell.org/package/servant-server-0.20/docs/Servant-Server.html#v:hoistServer and then pass the connection down to the handler using ReaderT https://github.com/danidiaz/comments-project/blob/3bb720124b31f0a8e351751bdcc6651ed75d9e27/comments/lib/Comments/Runner.hs#L57
It works, but I'm kinda unhappy about it because it forces you to use ReaderT in those intermediate components that lie between the top-level handler and the repository component which actually uses the connection. 😕

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

Eric Torreborre mentions the need for some form of ReaderT at 33:05 in his "Wire all the things" talk:
https://youtu.be/fFCcvsbCrH8?t=1986

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

You might say "Well, that's not a problem, just make those intermediate components that don't care about the connection polymorphic over MonadUnliftIO! Later, when composing the application, they will be injected a repository that does know about the ReaderT and the connection. Problem solved."

That's true, but what if I wanted those intermediate components to be as dumb as possible? Just plain records of functions in IO, no monad transformers, and no polymorphism over the monad, either?

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

As an alternative to ReaderT and/or polymorphism over the effect monad, I could try to implement some form of "thread-local" storage. 🤔 Some kind of map indexed by ThreadId which would be injected only into those components (like the repository) that require the request-scoped info.

Entries would be allocated / deallocated in the "hoistServer" callback, much like with the ReaderT solution.

Intermediate components could use IO for effects and remain blissfully innocent of the shenanigans.

DiazCarrete,
@DiazCarrete@hachyderm.io avatar

The problem of course is that this solution would be less type-safe. If the repository expects an entry for the current ThreadId to exist in the map, and we forgot to set it earlier in the "hoistServer" callback, that would be a runtime error.

It would probably be less efficient as well.

DiazCarrete, (edited )
@DiazCarrete@hachyderm.io avatar

"I got rid of ReaderT and now my application is hanging by a thread"
https://discourse.haskell.org/t/i-got-rid-of-readert-and-now-my-application-is-hanging-by-a-thread/9330

DiazCarrete,
@DiazCarrete@hachyderm.io avatar
  • All
  • Subscribed
  • Moderated
  • Favorites
  • haskell
  • rosin
  • cisconetworking
  • GTA5RPClips
  • osvaldo12
  • khanakhh
  • DreamBathrooms
  • magazineikmin
  • Youngstown
  • everett
  • mdbf
  • slotface
  • InstantRegret
  • kavyap
  • cubers
  • megavids
  • modclub
  • normalnudes
  • Durango
  • thenastyranch
  • ethstaker
  • tacticalgear
  • ngwrru68w68
  • Leos
  • anitta
  • provamag3
  • tester
  • JUstTest
  • lostlight
  • All magazines