Skip to content

Commit

Permalink
Merge pull request #188 from rails/unless-exist
Browse files Browse the repository at this point in the history
Support unless_exist
  • Loading branch information
djmb committed Jul 23, 2024
2 parents c96b69c + 6a0b3d5 commit 4626c66
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 8 deletions.
2 changes: 1 addition & 1 deletion app/models/solid_cache/entry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def lock_and_write(key, &block)
uncached do
result = lock.where(key_hash: key_hash_for(key)).pick(:key, :value)
new_value = block.call(result&.first == key ? result[1] : nil)
write(key, new_value)
write(key, new_value) if new_value
new_value
end
end
Expand Down
23 changes: 17 additions & 6 deletions lib/solid_cache/store/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,27 @@ def read_serialized_entry(key, **options)
entry_read(key)
end

def write_entry(key, entry, raw: false, **options)
def write_entry(key, entry, raw: false, unless_exist: false, **options)
payload = serialize_entry(entry, raw: raw, **options)
# No-op for us, but this writes it to the local cache
write_serialized_entry(key, payload, raw: raw, **options)

entry_write(key, payload)
if unless_exist
written = false
entry_lock_and_write(key) do |value|
if value.nil? || deserialize_entry(value, **options).expired?
written = true
payload
end
end
else
written = entry_write(key, payload)
end

write_serialized_entry(key, payload, raw: raw, returning: written, **options)
written
end

def write_serialized_entry(key, payload, raw: false, unless_exist: false, expires_in: nil, race_condition_ttl: nil, **options)
true
def write_serialized_entry(key, payload, raw: false, unless_exist: false, expires_in: nil, race_condition_ttl: nil, returning: true, **options)
returning
end

def read_serialized_entries(keys)
Expand Down
4 changes: 3 additions & 1 deletion lib/solid_cache/store/entries.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ def entry_clear

def entry_lock_and_write(key, &block)
writing_key(key, failsafe: :increment) do
Entry.lock_and_write(key, &block)
Entry.lock_and_write(key) do |value|
block.call(value).tap { |result| track_writes(1) if result }
end
end
end

Expand Down
11 changes: 11 additions & 0 deletions test/unit/solid_cache_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ class SolidCacheTest < ActiveSupport::TestCase
cache = lookup_store(max_age: 7200)
assert_equal 7200, cache.max_age
end

def test_write_with_unless_exist
assert_equal true, @cache.write("foo", 1)
assert_equal false, @cache.write("foo", 1, unless_exist: true)
end

def test_write_expired_value_with_unless_exist
assert_equal true, @cache.write(1, "aaaa", expires_in: 1.second)
travel 2.seconds
assert_equal true, @cache.write(1, "bbbb", expires_in: 1.second, unless_exist: true)
end
end

class SolidCacheFailsafeTest < ActiveSupport::TestCase
Expand Down

0 comments on commit 4626c66

Please sign in to comment.