[Haskell-cafe] Database connection pool
Bas van Dijk
v.dijk.bas at gmail.com
Thu May 6 11:41:55 EDT 2010
On Thu, May 6, 2010 at 3:24 PM, Michael Snoyman <michael at snoyman.com> wrote:
>
>
> On Thu, May 6, 2010 at 9:13 AM, Bryan O'Sullivan <bos at serpentine.com> wrote:
>>
>> On Wed, May 5, 2010 at 10:51 PM, Michael Snoyman <michael at snoyman.com>
>> wrote:
>>>
>>> * When a connection is released, is goes to the end of the pool, so
>>> connections get used evenly (not sure if this actually matters in practice).
>>
>> In practice, you're better off letting idle connections stay that way,
>> because then your DB server can close connections and free up resources. In
>> other words, when you're done with a connection, put it at the front of the
>> reuse queue, not the back.
>> You'll also want to handle the possibility that a connection that you grab
>> from the pool has been closed by the server. Many connection pooling
>> implementations I've seen get this wrong in subtle or expensive ways.
>
> Thanks for the feedback. I've gone ahead and implemented a simple resource
> pool module. Since I need it to work with monad transformer stacks, I've
> built it on top of MonadCatchIO-transformers. I've put the code up in a gist
> on github[1]. I would appreciate if anyone could review this, especially to
> make sure the exception handling code is correct. block and unblock in
> particular concern me.
> Thanks,
> Michael
> [1] http://gist.github.com/392078
In 'withPool' you correctly call 'block' to block (or mask)
asynchronous exceptions so that when you remove a resource from the
pool you can be sure that it will be added to the pool in the end,
even if an asynchronous exception is thrown to you in the middle of
your computation.
So it looks like your code is safe. However 'withPool' contains, what
I call, an asynchronous exception "wormhole".
'insertResource' calls 'modifyMVar_' which calls 'takeMVar' which will
block when the MVar is taken by another thread executing 'withPool'.
Now any operation which may itself block is, so called,
"interruptible". Interruptible means that even in the scope of a
'block' the operation will unblock (or unmask) asynchronous
exceptions! See [1] for details.
Note that I recently discussed this problem[2] on the libraries list
and also note that Simon Marlow is working on a solution.
I would advise you to replace the MVars with TVars which don't suffer
from asynchronous exception wormholes.
Regards,
Bas
[1] http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Control-Exception.html#13
[2] http://hackage.haskell.org/trac/ghc/ticket/4035
More information about the Haskell-Cafe
mailing list