Skip to content

Commit

Permalink
lazy loading data objects session data
Browse files Browse the repository at this point in the history
  • Loading branch information
fgrehm committed Jul 14, 2010
1 parent 09a4dde commit 71e8445
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 26 deletions.
55 changes: 34 additions & 21 deletions lib/harbor/contrib/session/data_objects.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,53 @@ class Session
##
class DataObjects < Harbor::Session::Abstract

class SessionHash < Hash
def initialize(instance)
super()
@instance = instance
merge!(@instance[:data])
class SessionHash
def initialize(raw)
@raw = raw
@data = nil
end

def [](key)
key == :session_id ? @instance[:session_id] : super
if key == :session_id
@raw[:session_id]
else
load_data![key]
end
end

def []=(key, value)
raise ArgumentError.new("You cannot manually set the session_id for a session.") if key == :session_id

super
load_data![key] = value
end

def data_loaded?
not @data.nil?
end

def load_data!
return @data if data_loaded?

@data = DataObjects.load(@raw[:data])
end

def to_hash
{}.merge(reject { |key,| key == :session_id })
@data
end
end

def self.load_session(cookie)
create_session_table unless session_table_exists?

session = if expire_after = Harbor::Session.options[:expire_after]
raw_session = if expire_after = Harbor::Session.options[:expire_after]
get_raw_session(cookie, Time.now - expire_after)
else
get_raw_session(cookie)
end

session ||= create_session
raw_session ||= create_session

SessionHash.new(session)
SessionHash.new(raw_session)
end

def self.commit_session(data, request)
Expand Down Expand Up @@ -85,10 +98,10 @@ def self.create_session_table

def self.create_session(data = {})
session_id = `uuidgen`.chomp
data = self.dump(data)

cmd = connection.create_command("INSERT INTO sessions (id, data, created_at, updated_at) VALUES (?, ?, ?, ?);")

cmd.execute_non_query(session_id, self.dump(data), Time.now, Time.now)
cmd = connection.create_command("INSERT INTO sessions (id, data, created_at, updated_at) VALUES (?, ?, ?, ?);")
cmd.execute_non_query(session_id, data, Time.now, Time.now)

{:session_id => session_id, :data => data}
end
Expand All @@ -113,26 +126,26 @@ def self.get_raw_session(cookie, updated_at=nil)

raw = {}
raw[:session_id] = reader.values[0]
raw[:data] = self.load(reader.values[1])
raw[:data] = reader.values[1]

reader.close

raw
end

protected

def self.connection
Harbor::Session.options[:connection]
end

def self.dump(data)
Base64.encode64(Marshal.dump(data))
end

def self.load(data)
Marshal.load(Base64.decode64(data))
end

protected

def self.connection
Harbor::Session.options[:connection]
end
end
end
end
Expand Down
34 changes: 29 additions & 5 deletions test/contrib/session/data_objects_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def setup
end

def teardown
# This should be done otherwise we might have trouble with connection pool
@connection.create_command('DROP TABLE sessions').execute_non_query if Harbor::Contrib::Session::DataObjects.session_table_exists?
@connection.close

Harbor::Contrib::Session::DataObjects.instance_eval do
@table_exists = nil
end
Expand Down Expand Up @@ -90,7 +94,8 @@ def test_commit_session

session_from_db = get_raw_session(session[:session_id])

expected_data = { :user_id => 10 }
expected_data = Harbor::Contrib::Session::DataObjects.dump({ :user_id => 10 })

assert_equal expected_data, session_from_db[:data]
assert_equal cookie[:value], session_from_db[:session_id]
end
Expand All @@ -106,28 +111,47 @@ def test_session_timeout

Harbor::Contrib::Session::DataObjects.create_session_table

session = create_session({ :user_id => 4 })
user_id = 4
session = create_session({ :user_id => user_id })
request = CookieRequest.new
request.cookies["harbor.session"] = session[:session_id]

time_elapsed = timeout-10
assert_session_valid_and_save(time_elapsed, request)
assert_session_valid_and_save(time_elapsed, request, user_id)

time_elapsed += timeout-10
assert_session_valid_and_save(time_elapsed, request)
assert_session_valid_and_save(time_elapsed, request, user_id)

time_elapsed += timeout+1
assert_session_expired(time_elapsed, request)
ensure
Harbor::Session.options[:expire_after] = nil
end

def test_data_is_lazy_parsed
Harbor::Contrib::Session::DataObjects.create_session_table

session = create_session({ :user_id => 4 })
request = CookieRequest.new
request.cookies["harbor.session"] = session[:session_id]

request_session = Harbor::Session.new(request)

assert request_session.data.instance_variable_get(:@data).nil?

# Parses data
request_session[:user_id]

assert ! request_session.data.instance_variable_get(:@data).nil?
end

protected
def assert_session_valid_and_save(time_elapsed, request)
def assert_session_valid_and_save(time_elapsed, request, user_id)
Time.warp(time_elapsed) do
request_session = Harbor::Session.new(request)

assert_equal 1, session_records_count
assert_equal user_id, request_session[:user_id]

request_session.save
end
Expand Down

0 comments on commit 71e8445

Please sign in to comment.