diff --git a/README.md b/README.md index 1f0164c..cc236c3 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1 false == limiter.exceeded? # => GET "limiter" ``` -Lists, unique lists, sets, and ordered sets support expiration: +Lists, unique lists, sets, ordered sets, and hashes support expiration: ```ruby set = Kredis.set "myset", expires_in: 1.second diff --git a/lib/kredis/attributes.rb b/lib/kredis/attributes.rb index 2ef7cfa..8f75db4 100644 --- a/lib/kredis/attributes.rb +++ b/lib/kredis/attributes.rb @@ -76,8 +76,8 @@ def kredis_limiter(name, limit:, key: nil, config: :shared, after_change: nil, e kredis_connection_with __method__, name, key, limit: limit, config: config, after_change: after_change, expires_in: expires_in end - def kredis_hash(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil) - kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change + def kredis_hash(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil, expires_in: nil) + kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change, expires_in: expires_in end def kredis_boolean(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil) diff --git a/lib/kredis/types.rb b/lib/kredis/types.rb index 6fdedb0..1c8e855 100644 --- a/lib/kredis/types.rb +++ b/lib/kredis/types.rb @@ -57,8 +57,8 @@ def enum(key, values:, default:, config: :shared, after_change: nil) type_from(Enum, config, key, after_change: after_change, values: values, default: default) end - def hash(key, typed: :string, default: nil, config: :shared, after_change: nil) - type_from(Hash, config, key, after_change: after_change, default: default, typed: typed) + def hash(key, typed: :string, default: nil, config: :shared, after_change: nil, expires_in: nil) + type_from(Hash, config, key, after_change: after_change, default: default, typed: typed, expires_in: expires_in) end def list(key, default: nil, typed: :string, config: :shared, after_change: nil, expires_in: nil) diff --git a/lib/kredis/types/hash.rb b/lib/kredis/types/hash.rb index b441a19..01d22ed 100644 --- a/lib/kredis/types/hash.rb +++ b/lib/kredis/types/hash.rb @@ -4,6 +4,7 @@ class Kredis::Types::Hash < Kredis::Types::Proxying prepend Kredis::DefaultValues + include Kredis::Expiration proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists? @@ -18,7 +19,9 @@ def []=(key, value) end def update(**entries) - hset entries.transform_values { |val| type_to_string(val, typed) }.compact if entries.flatten.any? + with_expiration do + hset entries.transform_values { |val| type_to_string(val, typed) }.compact if entries.flatten.any? + end end def values_at(*keys) diff --git a/test/attributes_test.rb b/test/attributes_test.rb index 2eed8b7..306ec66 100644 --- a/test/attributes_test.rb +++ b/test/attributes_test.rb @@ -46,6 +46,7 @@ class Person kredis_string :temporary_password, expires_in: 1.second kredis_hash :high_scores, typed: :integer kredis_hash :high_scores_with_default_via_lambda, typed: :integer, default: ->(p) { { high_score: JSON.parse(p.scores).max } } + kredis_hash :high_scores_with_ttl, typed: :integer, expires_in: 1.second kredis_boolean :onboarded kredis_boolean :adult_with_default_via_lambda, default: ->(p) { Date.today.year - p.birthdate.year >= 18 } kredis_limiter :update_limit, limit: 3, expires_in: 1.second @@ -404,6 +405,14 @@ class AttributesTest < ActiveSupport::TestCase assert_equal({ "high_score" => 28 }, @person.high_scores_with_default_via_lambda.to_h) end + test "hash with ttl" do + @person.high_scores_with_ttl.update(the_lost_viking: 99) + assert_equal({ "the_lost_viking" => 99 }, @person.high_scores_with_ttl.to_h) + + sleep 1.1 + assert_equal({}, @person.high_scores_with_ttl.to_h) + end + test "boolean" do @person.onboarded.value = true assert @person.onboarded.value diff --git a/test/types/hash_test.rb b/test/types/hash_test.rb index ef1f0de..6b2fd81 100644 --- a/test/types/hash_test.rb +++ b/test/types/hash_test.rb @@ -130,4 +130,14 @@ class HashTest < ActiveSupport::TestCase assert_nil @hash["key"] assert_equal "value2", @hash["key2"] end + + test "support ttl" do + @hash = Kredis.hash "myhash", expires_in: 1.second + @hash[:key] = :value + @hash.update("key2" => "value2", "key3" => "value3") + assert_equal "value", @hash[:key] + + sleep 1.1 + assert_equal [], @hash.keys + end end