[Web-SIG] and now for something completely different!

Ian Bicking ianb at colorstudy.com
Tue Aug 16 18:54:45 CEST 2005


mike bayer wrote:
> - because a "read" operation also registers a "last accessed time" data
> member, its not using multiple reader/single writer style locking,
> everyone is a writer.  However, since I am sensitive to iframes, ajax
> calls, and dynamic image calls hitting the same session concurrently
> within a request which I'd rather not slow down, I do something less than
> optimal which is I open the session store and read the full thing into
> memory first when its accessed, and then immediately unlock.  This
> obviously can create problems for an application that is storing huge
> amounts of data in its session which is not required in full for any one
> request.

I think we can all agree that we're not expecting sessions to be primary 
storage for large objects, so we shouldn't worry too much about this.

However, as a use case for objects derived from the session, consider an 
upload form with validation.  If someone uploads a large file but has an 
invalid form, you might want to keep the file around on the server side. 
  You can't put it in the form (hidden or not) because then you 
needlessly retransfer the file twice.  You can't leave the filename in 
the input field, because browsers don't allow that.

So in a lot of ways this is where it would be nice to put a big file in 
the session.  But you should really put it in a temporary directory and 
put the filename in the session (you could put the filename in a signed 
field in the form, but ignore that for now).  The advantage of putting 
it in the session is that the session has tracking, a timeout, etc.

So with the API I gave you might do:

session['upload_filename'] = '/tmp/foo.jpg'
session.store.expire_session_callbacks.append(delete_upload_filename)

def delete_upload_filename(session_id):
     session = session_store.load_session_read_only(session_id)
     if 'upload_filename' in session:
         filename = session['upload_filename']
         if os.path.exists(filename):
             os.unlink(filename)

Though there's a couple issues.  The sessino store should be passed 
along with the session ID.  It should be specified that loading a 
session from this callback will not cancel its expiration.  Maybe 
per-session callbacks should be allowed; in which case the callbacks 
would have to be identifiable by a string or some pickleable value, 
since you can't pickle the functions themselves.  I suppose you could 
implement the callback as an instance with a __call__ method, which 
pickle turns into a class name plus __dict__ values.  I hate overusing 
__call__; if it has to be an instance (to be pickleable), then might as 
well give it a method name, and maybe call other methods as well.  Then 
it  essentially becomes an ad hoc event system.

-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org


More information about the Web-SIG mailing list