Skip to content
Browse files

Integrate with Rack and Rails session store

Change-Id: I0963e753efcce320fa1e350326e33a1cd520c79c
Reviewed-on: http://review.couchbase.org/17280
Tested-by: Sergey Avseyev <sergey.avseyev@gmail.com>
Reviewed-by: Chris Anderson <jchris@couchbase.com>
  • Loading branch information...
1 parent c77ee65 commit ba3487709658f8c1d1c65c31a8ec65b1159ee8d9 @avsej committed Jun 14, 2012
Showing with 142 additions and 0 deletions.
  1. +38 −0 lib/action_dispatch/middleware/session/couchbase_store.rb
  2. +104 −0 lib/rack/session/couchbase.rb
View
38 lib/action_dispatch/middleware/session/couchbase_store.rb
@@ -0,0 +1,38 @@
+require 'active_support/cache'
+require 'action_dispatch/middleware/session/abstract_store'
+require 'rack/session/couchbase'
+require 'couchbase'
+
+module ActionDispatch
+ module Session
+
+ # This is Couchbase-powered session store for Rails applications
+ #
+ # To use it just update your `config/initializers/session_store.rb` file
+ #
+ # require 'action_dispatch/middleware/session/couchbase_store'
+ # AppName::Application.config.session_store :couchbase_store
+ #
+ # Or remove this file and add following line to your `config/application.rb`:
+ #
+ # require 'action_dispatch/middleware/session/couchbase_store'
+ # config.session_storage = :couchbase_store
+ #
+ # You can also pass additional options:
+ #
+ # require 'action_dispatch/middleware/session/couchbase_store'
+ # session_options = {
+ # :expire_after => 5.minutes,
+ # :couchbase => {:bucket => "sessions", :default_format => :marshal}
+ # }
+ # config.session_storage = :couchbase_store, session_options
+ #
+ # By default sessions will be serialized to JSON, to allow analyse them
+ # using Map/Reduce.
+ #
+ class CouchbaseStore < Rack::Session::Couchbase
+ include Compatibility
+ include StaleSessionCheck
+ end
+ end
+end
View
104 lib/rack/session/couchbase.rb
@@ -0,0 +1,104 @@
+# Author:: Couchbase <info@couchbase.com>
+# Copyright:: 2011, 2012 Couchbase, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'rack/session/abstract/id'
+require 'couchbase'
+require 'thread'
+
+module Rack
+ module Session
+
+ # This is Couchbase-powered session store for rack applications
+ #
+ # To use it just load it as usual middleware in your `config.ru` file
+ #
+ # require 'rack/session/couchbase'
+ # use Rack::Session::Couchbase
+ #
+ # You can also pass additional options:
+ #
+ # require 'rack/session/couchbase'
+ # use Rack::Session::Couchbase, :expire_after => 5.minutes,
+ # :couchbase => {:bucket => "sessions", :default_format => :marshal}
+ #
+ # By default sessions will be serialized to JSON, to allow analyse them
+ # using Map/Reduce.
+ #
+ class Couchbase < Abstract::ID
+ attr_reader :mutex, :pool
+
+ DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge(
+ :couchbase => {:default_format => :document, :key_prefix => 'rack:session:'})
+
+ def initialize(app, options = {})
+ # Support old :expires option
+ options[:expire_after] ||= options[:expires]
+ super
+
+ @default_options[:couchbase][:default_ttl] ||= options[:expire_after]
+ @default_options[:couchbase][:key_prefix] ||= options[:namespace]
+ @namespace = @default_options[:couchbase][:key_prefix]
+ @mutex = Mutex.new
+ @pool = ::Couchbase.connect(@default_options[:couchbase])
+ end
+
+ def generate_sid
+ loop do
+ sid = super
+ break sid unless @pool.get(sid)
+ end
+ end
+
+ def get_session(env, sid)
+ with_lock(env, [nil, {}]) do
+ unless sid and session = @pool.get(sid)
+ sid, session = generate_sid, {}
+ @pool.set(sid, session)
+ end
+ [sid, session]
+ end
+ end
+
+ def set_session(env, session_id, new_session, options)
+ with_lock(env, false) do
+ @pool.set session_id, new_session, options
+ session_id
+ end
+ end
+
+ def destroy_session(env, session_id, options)
+ with_lock(env) do
+ @pool.delete(session_id)
+ generate_sid unless options[:drop]
+ end
+ end
+
+ def with_lock(env, default = nil)
+ @mutex.lock if env['rack.multithread']
+ yield
+ rescue Couchbase::Error::Connect, Couchbase::Error::Timeout
+ if $VERBOSE
+ warn "#{self} is unable to find Couchbase server."
+ warn $!.inspect
+ end
+ default
+ ensure
+ @mutex.unlock if @mutex.locked?
+ end
+ end
+ end
+end

0 comments on commit ba34877

Please sign in to comment.
Something went wrong with that request. Please try again.