module Merb module SessionMixin def setup_session MERB_LOGGER.info("Setting up session") before = cookies[session_id_key] @session , cookies[session_id_key] = Merb::MemorySession.persist(cookies[session_id_key]) @_new_cookie = cookies[session_id_key] != before end def finalize_session MERB_LOGGER.info("Finalize session") set_cookie(session_id_key, cookies[session_id_key], Time.now+Merb::Const::WEEK*2) if @_new_cookie end end class MemorySession class << self RAND_CHARS = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z'] # Generates a new session ID and creates a row for the new session in the database. def generate rand_max = RAND_CHARS.size sid = (0...32).inject("") { |ret,_| ret << RAND_CHARS[rand(rand_max)] } [create(:session_id => sid, :data => {}), sid] end # Gets the existing session based on the session_id available in cookies. # If none is found, generates a new session. def persist(session_id) if session_id session = self[session_id] sid = session_id end unless session session, sid = generate end [session, sid] end def setup(opts={}) @opts = opts @sessions = Hash.new @timestamps = Hash.new @mutex = Mutex.new @session_ttl = opts.fetch(:session_ttl, 60*60) # default 1 hour start_timer self end def create(opts={}) self[opts[:session_id]] = opts[:data] end def [](key) @mutex.synchronize { @timestamps[key] = Time.now @sessions[key] } end def []=(key, val) @mutex.synchronize { @timestamps[key] = Time.now @sessions[key] = val } end def delete(key) @mutex.synchronize { @sessions.delete(key) } end def reap_old_sessions @timestamps.each do |key,stamp| if stamp + @session_ttl < Time.now delete(key) end end GC.start end def start_timer Thread.new do loop { sleep @session_ttl reap_old_sessions } end end def sessions @sessions end end # end singleton class end # end DRbSession end