Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions lib/utopia/session/lazy_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ def initialize(&block)
@loader = block
end

# The loaded session values, if already loaded.
# @returns [Hash | Nil] The loaded values.
attr :values

# Fetch a value by key, loading the hash if necessary.
# @parameter key [Object] The key.
# @returns [Object | Nil] The value.
Expand Down Expand Up @@ -66,10 +62,20 @@ def changed?
@changed
end

# Load and return the underlying values.
# @returns [Hash] The loaded values.
def load!
@values ||= @loader.call
# Persist the session values if they have changed or require updating.
# @parameter timeout [Numeric | Nil] The maximum age before an update is required.
# @yields {|values, updated_at| ...} The loaded values and their update time.
# @returns [Object | Nil] The result of the block if persistence was required.
def persist(timeout = nil)
return unless needs_update?(timeout)

values = load!
updated_at = values[:updated_at] = Time.now.utc

result = yield(values, updated_at)
@changed = false

return result
end

# Check whether the underlying values have been loaded.
Expand All @@ -93,6 +99,13 @@ def needs_update?(timeout = nil)

return false
end

private

# Load and return the underlying values.
def load!
@values ||= @loader.call
end
end
end
end
10 changes: 2 additions & 8 deletions lib/utopia/session/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,8 @@ def prepare_session(request)
end

def update_session(session_hash, headers)
if session_hash.needs_update?(@update_timeout)
values = session_hash.values

values[:updated_at] = Time.now.utc

data = encrypt(session_hash.values)

commit(data, values[:updated_at], headers)
session_hash.persist(@update_timeout) do |values, updated_at|
commit(encrypt(values), updated_at, headers)
end
end

Expand Down
38 changes: 38 additions & 0 deletions test/utopia/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,42 @@ def before

expect(hash).to be(:needs_update?)
end

it "should persist changed values" do
hash = Utopia::Session::LazyHash.new do
{a: 10}
end

hash[:a] = 20
persisted_at = Time.now.utc

result = hash.persist do |values, updated_at|
expect(values[:a]).to be == 20
expect(updated_at).to be >= persisted_at
expect(values[:updated_at]).to be_equal(updated_at)

:complete
end

expect(result).to be == :complete
expect(hash).not.to be(:changed?)
expect(hash).not.to be(:respond_to?, :values)
expect(hash).not.to be(:respond_to?, :load!)
end

it "should retain changes if persistence fails" do
hash = Utopia::Session::LazyHash.new do
{a: 10}
end

hash[:a] = 20

expect do
hash.persist do
raise "Persistence failed!"
end
end.to raise_exception(RuntimeError, message: be == "Persistence failed!")

expect(hash).to be(:changed?)
end
end
Loading