Here's an interesting fact: Whenever I hit MyApp with an invalid
session id (i.e. one, that isn't in the store), the plugin tries to
insert this exact session id. If two concurrent requests with an
invalid session come in, they both try to (re-)create this invalid
session. This is due to the use of find_or_create(). But shouldn't the
correct approach be:

a) Try to find the session, e.g. $self->model->find({ $self->id_field => $key })
b) If found, use this session because it's still valid.
c) If not found, create() an entirely NEW(!) session, with a new
session-ID and insert it.

Why on earth would we want to insert an invalid session into the
database, just to delete it afterwards because it was invalid and then
create a fresh session? Here's an SQL log that shows what's going on:

BEGIN WORK
BEGIN WORK
SELECT me.id, me.a_session, me.expires FROM sessions2 me WHERE ( me.id
= ? ): 'session:invalid'
SELECT me.id, me.a_session, me.expires FROM sessions2 me WHERE ( me.id
= ? ): 'session:invalid'
INSERT INTO sessions2 ( id) VALUES ( ? ): 'session:invalid'
INSERT INTO sessions2 ( id) VALUES ( ? ): 'session:invalid'
COMMIT
DELETE FROM sessions2 WHERE ( id = ? ): 'session:invalid'
ROLLBACK
DELETE FROM sessions2 WHERE ( id = ? ): 'flash:invalid'
BEGIN WORK
SELECT me.id, me.a_session, me.expires FROM sessions2 me WHERE ( me.id
= ? ): 'session:new-session'
INSERT INTO sessions2 ( id) VALUES ( ? ): 'session:new-session'
COMMIT
UPDATE sessions2 SET a_session = ?, expires = ? WHERE ( id = ? ):
'foo', '1318239160', 'session:new-session'

So, isn't the use of find_or_create() just plain wrong or am I seeing
things here? :)

--Toby




On Sat, Oct 8, 2011 at 2:23 PM, Janne Snabb <sn...@epipe.com> wrote:
> On Sat, 8 Oct 2011, Janne Snabb wrote:
>
>>     return $self->model->find_or_create({ $self->id_field => $key })
>
> Just an update:
>
> I discussed about this with mst on irc and we concluded that my
> initial suggestion for the fix is also not correct. It is likely
> to eliminate the SQL error but also likely to cause spurious behaviour
> in the upper layers.
>
> The upper layer (which I have not looked at, is there a call/inheritance
> graph of Catalyst available somewhere? :) should get notified that
> the old session is gone, thus we can not just autovivify it in the
> storage with the old id. Rather a new id should be issued so that
> the upper layers will have a chance of noticing what happened. I
> think that would also eliminate the collisions (as the new id is a
> new random string).
>
> *::Session::Storage::Cache::* is presumambly a better choice than
> DBI/DBIC in the usual case.
>
> --
> Janne Snabb / EPIPE Communications
> sn...@epipe.com - http://epipe.com/
>
> _______________________________________________
> List: Catalyst@lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/
>

_______________________________________________
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/

Reply via email to