I've written about this issue a couple of times in the past and it
seems that this still hasn't been fixed. Here's what's happening:
1. Request A comes in with an expired session cookie, C::P::Session
tries to find the session for the given cookie but finds nothing.
2. Meanwhile, Request B comes in, also trying to find the session for
the same(!) cookie and goes away with empty hands as well.
3. Both requests try to insert a new session, one succeeds, the other
dies(!) with a duplicate key constraint error from MySQL.
If this would happen once in a while, I'd be okay with it, but it
happens every 3-5 minutes. We are using the latest versions of
everything - except DBIx::Class which is still on 0.08107 - and the
sessions table is InnoDB with big enough columns.
Now, in this day and age concurrent requests are not that seldom. The
POD of C::P::Session even describes this race-condition but the author
assumes that the session is just silently overwritten which isn't the
case when using a database backend with key constraints. Imagine a
page loading some additional content via AJAX or some web-bug pixels
and you have exactly the scenario described above. Is it really
desirable that the App dies on the user when this happens? Shouldn't
we handle this in a more sane way, maybe by just ignoring the error
because it operates on the same session anyways?
I've put together a little test app and an AnyEvent-based script to
run concurrent requests against the App which should illustrate the
problem. I'd appreciate it if you folks could check it out and tell me
if you're seeing the problem as well:
Of course the App should be started with a forking server to allow
concurrent requests, for example:
CATALYST_DEBUG=0 CATALYST_ENGINE="HTTP::Prefork" perl
Afterwards you can run the testing script "crash_sessions.pl" which
should give you an HTTP 500 error after you've run it a couple of
times. A look at the App server output will hopefully give you the
duplicate key constraint error I'm talking about :)
Any ideas on how best to go about fixing this?
Thanks a lot!