<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -46,21 +46,31 @@ module Rack
             end until /^STORED/ =~ ret
           end
         end
+        class &lt;&lt; session
+          @deleted = []
+          def delete key
+            (@deleted||=[]) &lt;&lt; key
+            super
+          end
+        end
         [sid, session]
       end
 
       def set_session(env, sid)
+        session = env['rack.session']
         options = env['rack.session.options']
-        expiry = options[:expire_after] || 0
+        expiry  = options[:expire_after] || 0
         o, s = @mutex.synchronize do
           old_session = @pool.get(sid)
           unless old_session.is_a?(Hash)
-            warn 'Session not properly initialized.'
+            warn 'Session not properly initialized.' if $DEBUG
             old_session = {}
             @pool.add sid, old_session, expiry
           end
-          session = old_session.merge(env['rack.session'])
-          @pool.set sid, session, expiry
+          session.instance_eval do
+            @deleted.each{|k| old_session.delete(k) } if defined? @deleted
+          end
+          @pool.set sid, old_session.merge(session), expiry
           [old_session, session]
         end
         s.each do |k,v|</diff>
      <filename>lib/rack/session/memcache.rb</filename>
    </modified>
    <modified>
      <diff>@@ -50,34 +50,51 @@ context &quot;Rack::Session::Memcache&quot; do
     res.body.should.include '&quot;counter&quot;=&gt;1'
   end
 
-  specify &quot;multithread: should merge sessions&quot; do
-    delta_incrementor = lambda do |env|
-      env['rack.session'] = env['rack.session'].dup
-      sleep 1
-      env['rack.session'][(Time.now.usec*rand).to_i] = true
-      incrementor.call(env)
-    end
+  specify &quot;multithread: should cleanly merge sessions&quot; do
     cache = Rack::Session::Memcache.new(incrementor)
+    drop_counter = Rack::Session::Memcache.new(proc do |env|
+      env['rack.session'].delete 'counter'
+      env['rack.session']['foo'] = 'bar'
+      [200, {'Content-Type'=&gt;'text/plain'}, env['rack.session'].inspect]
+    end)
+
     res = Rack::MockRequest.new(cache).get('/')
     res.body.should.equal '{&quot;counter&quot;=&gt;1}'
     cookie = res[&quot;Set-Cookie&quot;]
-    sess_id = cookie[/#{cache.key}=([^,;]+)/,1]
+    sess_id = cookie[/#{cache.key}=([^,;]+)/, 1]
+
+    res = Rack::MockRequest.new(cache).get('/', &quot;HTTP_COOKIE&quot; =&gt; cookie)
+    res.body.should.equal '{&quot;counter&quot;=&gt;2}'
+
+    r = Array.new(rand(7).to_i+2) do |i|
+      app = proc do |env|
+        env['rack.session'][i]  = Time.now
+        sleep 2
+        env['rack.session']     = env['rack.session'].dup
+        env['rack.session'][i] -= Time.now
+        incrementor.call(env)
+      end
+      Thread.new(cache.context(app)) do |run|
+        Rack::MockRequest.new(run).
+          get('/', &quot;HTTP_COOKIE&quot; =&gt; cookie, 'rack.multithread' =&gt; true)
+      end
+    end.reverse.map{|t| t.join.value }
 
-    cache = cache.context(delta_incrementor)
-    r = Array.new(rand(7).to_i+2).
-      map! do
-        Thread.new do
-          Rack::MockRequest.new(cache).get('/', &quot;HTTP_COOKIE&quot; =&gt; cookie, 'rack.multithread' =&gt; true)
-        end
-      end.
-      reverse!.
-      map!{|t| t.join.value }
-    session = cache.for.pool[sess_id] # for is needed by Utils::Context
-    session.size.should.be r.size+1 # counter
-    session['counter'].should.be 2 # meeeh
     r.each do |res|
       res['Set-Cookie'].should.equal cookie
-      res.body.should.include '&quot;counter&quot;=&gt;2'
+      res.body.should.include '&quot;counter&quot;=&gt;3'
     end
+
+    session = cache.pool[sess_id]
+    session.size.should.be r.size+1
+    session['counter'].should.be 3
+
+    res = Rack::MockRequest.new(drop_counter).get('/', &quot;HTTP_COOKIE&quot; =&gt; cookie)
+    res.body.should.include '&quot;foo&quot;=&gt;&quot;bar&quot;'
+
+    session = cache.pool[sess_id]
+    session.size.should.be r.size+1
+    session['counter'].should.be.nil?
+    session['foo'].should.equal 'bar'
   end
 end</diff>
      <filename>test/spec_rack_session_memcache.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c8006eda8f6211a879d2544b9150fefe369098fe</id>
    </parent>
  </parents>
  <author>
    <name>Scytrin dai Kinthra</name>
    <email>scytrin@gmail.com</email>
  </author>
  <url>http://github.com/chneukirchen/rack-mirror/commit/7d22320a8f1c4d6290a8dad37b26153bcf96f7ad</url>
  <id>7d22320a8f1c4d6290a8dad37b26153bcf96f7ad</id>
  <committed-date>2008-03-28T21:32:00-07:00</committed-date>
  <authored-date>2008-03-28T21:32:00-07:00</authored-date>
  <message>memcache.rb - Fixed immortal key bug, updated tests

Old multithread behaviour was to merge sessions, which would never delete
keys, even if deleted in the current session.

darcs-hash:20080329043246-f4dbf-a06869f81601926826828807e72fbca186cae6e3.gz</message>
  <tree>09b25453fd5452314aa76baf1629c5152b065e2c</tree>
  <committer>
    <name>Scytrin dai Kinthra</name>
    <email>scytrin@gmail.com</email>
  </committer>
</commit>
