paurkedal / ocaml-caqti

Cooperative-threaded access to relational data
https://paurkedal.github.io/ocaml-caqti/index.html
GNU Lesser General Public License v3.0
309 stars 36 forks source link

Add Caqti_lwt.with_connection_or_fail #62

Closed aantron closed 3 years ago

aantron commented 3 years ago

As the docstring says, this is an Lwt-friendly version of with_connection, which I end up defining in my code.

I want to do the same for Caqti_lwt.Pool.use — I also define an Lwt-version of it in my code. This seems to require some module gymnastics, however. Looking into that next.

paurkedal commented 3 years ago

I am not so found of adding exception-based error handling inside callbacks, as the connection interface is designed on the principle that any runtime errors are propagated as results. We would end up doubling up most of the connection functions with an _exn variant for consistency. I don't see a gain in doing that, since handers are merely meant to carry out transaction logic and collect the result. On the other hand, I don't want to enforce this on the rest of application, but for that purpose there is already the Caqti_lwt.or_fail which can easily be attached to a use/with_connection can.

Note that the functions from the connection module return errors from a polymorphic variant with also mixes with the rest of the Caqti API. I always define these for convenience:

val (>>=?) :
  ('a, 'e) result Lwt.t -> ('a -> ('b, 'e) result Lwt.t) ->
  ('b, 'e) result Lwt.t

val (>|=?) :
  ('a, 'e) result Lwt.t -> ('a -> 'b) ->
  ('b, 'e) result Lwt.t

val (let*?) :
  ('a, 'e) result Lwt.t -> ('a -> ('b, 'e) result Lwt.t) ->
  ('b, 'e) result Lwt.t

val (let+?) :
  ('a, 'e) result Lwt.t -> ('a -> 'b) ->
  ('b, 'e) result Lwt.t

With these, dealing with results inside callbacks shouldn't complicate the code. Custom errors can also be propagated from inside to outside by mixing the into the variant, with a custom or_fail if used.

aantron commented 3 years ago

Fair enough. Thanks for the reply!