in reply to RFC Singleton Sessions

I usually just create a session wrapper, so you can call something like MySession->get_sesssion() and it gives you back the session for the current user, dealing with cookies and caching the result as necessary.

Replies are listed 'Best First'.
Re^2: RFC Singleton Sessions
by derby (Abbot) on Dec 08, 2006 at 11:15 UTC

    [id://perrin], that makes sense for a normal request when the cookie is sent along with the request (or the session id is embedded in the url). What's probably missing from my OP is that initial request when the cookie is set -- in that case, what is MySession->get_session() doing to retrieve the just created session? You can't get the session id from the cookie (since you've just set it) and I really don't want to pass the session through several methods. In my mind, a singleton (per request) is what's needed but I'm not 100% certain since this is the first time I've had to deal with this particular situation (if I were doing the app from scratch, I'd code it in such a way as not to be in this situation!)

    -derby

      A singleton is basically the same thing as a global variable. In Perl, that's typically how they are implemented -- you put your session object into some package variable in the MySession namespace, or in mod_perl you might put in $r->pnotes.

      What this means for you is that any time you create a session object, either from a cookie or by generating a totally new one and adding a cookie, you keep the session object around in this global for anyone else who needs it during the request. At the end of the request, if you put it in a package variable and not pnotes, you have to make sure to clear it and save the session. Is this making more sense to you now?

        [id://perrin]. Yep clear. Basically, borrowing from Apache::Singleton, here's the relevant code.

        package My::Session; ... use vars qw( $GLOBAL_SESSION ); ... sub new { my( $class, $args ) = @_; $args->{log} ||= My::Log->new(); my $instance = $class->_get_instance( $args ); unless( defined $instance ) { $instance = $class->_new_instance( $args ); $class->_set_instance( $instance ); } return $instance; } sub _get_instance { my( $class, $args ) = @_; if( $ENV{MOD_PERL} ) { $args->{log}->debug( "Getting mod_perl session instance" ); my $req = Apache->request(); my $key = "$class\::_instance"; return $req->pnotes( $key ); } else { $args->{log}->debug( "Getting cgi session instance" ); return $GLOBAL_SESSION; } } sub _new_instance { my( $class, $args ) = @_; my $self = {}; $self->{log} = $args->{log}; $self->{log}->debug( "creating new session instance" ); bless $self, $class; # call method to load access privs here return $self; } sub _set_instance { my( $class, $instance ) = @_; if( $ENV{MOD_PERL} ) { $instance->{log}->debug( "setting new mod_perl instance" ); my $req = Apache->request(); my $key = "$class\::_instance"; $req->pnotes( $key, $instance ); } else { $instance->{log}->debug( "setting new cgi instance" ); $GLOBAL_SESSION = $instance; } }

        -derby