From fd7c98f7f6a89ad505b41c7a509a584fa2d389d5 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 15 Jan 2009 14:01:31 -0600 Subject: [PATCH] Add Locking middleware --- lib/rack.rb | 1 + lib/rack/lock.rb | 16 ++++++++++++++++ test/spec_rack_lock.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 0 deletions(-) create mode 100644 lib/rack/lock.rb create mode 100644 test/spec_rack_lock.rb diff --git a/lib/rack.rb b/lib/rack.rb index f0020c3..c64bfe4 100644 --- a/lib/rack.rb +++ b/lib/rack.rb @@ -38,6 +38,7 @@ module Rack autoload :Handler, "rack/handler" autoload :Head, "rack/head" autoload :Lint, "rack/lint" + autoload :Lock, "rack/lock" autoload :MethodOverride, "rack/methodoverride" autoload :Mime, "rack/mime" autoload :Recursive, "rack/recursive" diff --git a/lib/rack/lock.rb b/lib/rack/lock.rb new file mode 100644 index 0000000..9323852 --- /dev/null +++ b/lib/rack/lock.rb @@ -0,0 +1,16 @@ +module Rack + class Lock + FLAG = 'rack.multithread'.freeze + + def initialize(app, lock = Mutex.new) + @app, @lock = app, lock + end + + def call(env) + old, env[FLAG] = env[FLAG], false + @lock.synchronize { @app.call(env) } + ensure + env[FLAG] = old + end + end +end diff --git a/test/spec_rack_lock.rb b/test/spec_rack_lock.rb new file mode 100644 index 0000000..3be6fd3 --- /dev/null +++ b/test/spec_rack_lock.rb @@ -0,0 +1,40 @@ +require 'test/spec' + +require 'rack/mock' +require 'rack/lock' + +context "Rack::Lock" do + class Lock + attr_reader :synchronized + + def initialize + @synchronized = false + end + + def synchronize + @synchronized = true + yield + end + end + + specify "should call synchronize on lock" do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + app = Rack::Lock.new(lambda { }, lock) + lock.synchronized.should.equal false + app.call(env) + lock.synchronized.should.equal true + end + + specify "should set multithread flag to false" do + env = Rack::MockRequest.env_for("/") + app = Rack::Lock.new(lambda { |env| env['rack.multithread'] }) + app.call(env).should.equal false + end + + specify "should reset original multithread flag when exiting lock" do + env = Rack::MockRequest.env_for("/") + app = Rack::Lock.new(lambda { |env| env }) + app.call(env)['rack.multithread'].should.equal true + end +end -- 1.6.0.4