Skip to content

Api encouraging incorrect implementation #40

@turboMaCk

Description

@turboMaCk

This PR rotted a lot and should probably be closed: #28

Anyway I would like to instead open an issue to discuss the core problem it was attempting to address.

This library exposes 2 types of errors:

  1. WithNamedError is used for errors that come from implementation of this library (named argument not found)
  2. IO exceptions that happen within postgresql-simple

My claim is that one never wants to handle the 1 (it's implementation error not legitimate runtime error in most cases). But almost always wants to handle some subset of 2.

The problem

Putting WithNamedError thing aside lets clarify why IO exceptions matter.

Imagine a table with UNIQUE constrained. For obvious reasons when inserting data to the table there is an expected error that could happen - violation of unique constrained. This error most likely needs to be clearly communicated to caller - for instance the specific 400 response with information that name is taken in some form should be rendered by HTTP server.

The solution that this library encourages is to write 2 queries (why is explained bellow). One to check if given unique column doesn't already exist and then performing the insert. This solution is of course incorrect. In presence of concurrency some other thread could create conflicting entry in between the select and insert.

The correct solution is to perform insert and catch unique constrained violation. So what does it take to do this?

With postgresql-simple one works with IO so catching this means catching exception in IO monad. However with postgresql-simple-named this IO is lifted to LiftIO m => m. To catch the exception one needs to use construct that could catch it in the m (lifted IO context). For instance using Control.Exception.Lifted which is not part base or implement similar exception handler to this one. I claim that this is no good because good API should make correct implementation simpler not harder.

Proposed solutions

There are multiple potential solutions. I have some ideas myself but first I would like to see what others think.

Currently there is an issue for one possible approach #27

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions