durusmail: quixote-users: PATCH: deferred session ID creation
PATCH: deferred session ID creation
2002-10-18
PATCH: deferred session ID creation
Jonathan Corbet
2002-10-18
In case it's useful to others...

Quixote currently generates a session ID for every anonymous request.  It
checks that session ID twice - once on creation to avoid conflicts (the
check is racy, of course, but I'm not too concerned about it), and once
when it considers removing it from the session directory.  But most
anonymous requests will remain anonymous.  So why not defer creating (and
checking) the session ID until you know you're going to save the session?

This little patch has been running production on LWN for a while now; it
saves two database round trips for every anonymous request, and one round
trip when a session is in use.

jon


--- session.py.0.5.1    2002-10-18 14:33:34.000000000 -0600
+++ session.py  2002-10-18 14:38:35.000000000 -0600
@@ -182,6 +182,7 @@
         if not isinstance(session, self.session_class):
             raise TypeError("session not an instance of %r: %r"
                             % (self.session_class, session))
+        assert session.id is not None, "session ID not set"
         assert session_id == session.id, "session ID mismatch"
         self.sessions[session_id] = session

@@ -248,18 +249,19 @@
         else:
             return id

-    def _create_session (self, request):
+    def _make_session_id (self):
         # Generate a session ID, which is just the value of the session
         # cookie we are about to drop on the user.  (It's also the key
         # used with the session manager mapping interface.)
         id = None
         while id is None or self.has_session(id):
             id = "%016X" % randlong(8)  # 64-bit random number
+        return id

-        # Create a session object which will be looked up the next
-        # time this user comes back carrying the session cookie
-        # with the session ID just generated.
-        return self.new_session(request, id)
+    def _create_session (self, request):
+        # Create a new session object, with no ID for now - one will
+        # be assigned later if we save the session.
+        return self.new_session(request, None)

     def get_session (self, request):
         """get_session(request : HTTPRequest) -> Session
@@ -321,14 +323,15 @@
             # Session has no useful info -- forget it.  If it previously
             # had useful information and no longer does, we have to
             # explicitly forget it.
-            if self.has_session(session.id):
+            if session.id and self.has_session(session.id):
                 del self[session.id]
                 self.revoke_session_cookie(request)
             return

-        if not self.has_session(session.id):
+        if session.id is None:
             # This is the first time this session has had useful
             # info -- store it and set the session cookie.
+            session.id = self._make_session_id()
             self[session.id] = session
             self.set_session_cookie(request, session.id)


reply