From eb1e5dd87e901316e0f5f618ee4440674706eee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Garc=C3=ADa=20del=20Canto?= Date: Wed, 25 Oct 2023 03:36:29 +0200 Subject: [PATCH] feat(set_exat_pxat): Add EXAT and PXAT arguments to the SET redis command (#280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related with this issue https://github.com/sds/mock_redis/issues/279 * Documentation for the feature here: https://redis.io/commands/set/ * Added tests for SET ... EXAT and PXAT on a valid and invalid key Hope you find it useful 😄 --- CHANGELOG.md | 4 ++++ lib/mock_redis/string_methods.rb | 19 ++++++++++++++-- lib/mock_redis/version.rb | 2 +- spec/commands/set_spec.rb | 38 ++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 145f09c..e6175e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # MockRedis Changelog +### 0.38.0 + +* Add support for `EXAT` AND `PXAT` arguments to `SET` command + ### 0.37.0 * Require Ruby 2.7 or newer, since Ruby 2.6 and older are EOL diff --git a/lib/mock_redis/string_methods.rb b/lib/mock_redis/string_methods.rb index 1501c77..f6fb5a4 100644 --- a/lib/mock_redis/string_methods.rb +++ b/lib/mock_redis/string_methods.rb @@ -210,9 +210,10 @@ def mapped_msetnx(hash) msetnx(*hash.to_a.flatten) end - # Parameer list required to ensure the ArgumentError is returned correctly + # Parameter list required to ensure the ArgumentError is returned correctly # rubocop:disable Metrics/ParameterLists - def set(key, value, ex: nil, px: nil, nx: nil, xx: nil, keepttl: nil, get: nil) + def set(key, value, ex: nil, px: nil, exat: nil, pxat: nil, nx: nil, xx: nil, keepttl: nil, + get: nil) key = key.to_s retval = self.get(key) if get @@ -248,6 +249,20 @@ def set(key, value, ex: nil, px: nil, nx: nil, xx: nil, keepttl: nil, get: nil) pexpire(key, px) end + if exat + if exat == 0 + raise Redis::CommandError, 'ERR invalid expire time in set' + end + expireat(key, exat) + end + + if pxat + if pxat == 0 + raise Redis::CommandError, 'ERR invalid expire time in set' + end + pexpireat(key, pxat) + end + if get retval else diff --git a/lib/mock_redis/version.rb b/lib/mock_redis/version.rb index 0e051fe..86e98a5 100644 --- a/lib/mock_redis/version.rb +++ b/lib/mock_redis/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. class MockRedis - VERSION = '0.37.0' + VERSION = '0.38.0' end diff --git a/spec/commands/set_spec.rb b/spec/commands/set_spec.rb index 6cdb177..b14000a 100644 --- a/spec/commands/set_spec.rb +++ b/spec/commands/set_spec.rb @@ -20,6 +20,18 @@ end.to raise_error(Redis::CommandError, 'ERR invalid expire time in set') end + it 'raises an error for EXAT seconds = 0' do + expect do + @redises.set('mock-redis-test', 1, exat: 0) + end.to raise_error(Redis::CommandError, 'ERR invalid expire time in set') + end + + it 'raises an error for PXAT seconds = 0' do + expect do + @redises.set('mock-redis-test', 1, pxat: 0) + end.to raise_error(Redis::CommandError, 'ERR invalid expire time in set') + end + it 'accepts NX' do @redises.del(key) expect(@redises.set(key, 1, nx: true)).to eq(true) @@ -33,6 +45,16 @@ expect(@redises.set(key, 1, xx: true)).to eq(true) end + it 'accepts EXAT' do + @redises.del(key) + expect(@redises.set(key, 1, exat: 1_697_197_606)).to eq('OK') + end + + it 'accepts PXAT' do + @redises.del(key) + expect(@redises.set(key, 1, exat: 1_697_197_589_362)).to eq('OK') + end + it 'accepts GET on a string' do expect(@redises.set(key, '1')).to eq('OK') expect(@redises.set(key, '2', get: true)).to eq('1') @@ -129,6 +151,22 @@ allow(Time).to receive(:now).and_return(@now + 600 / 1000.to_f) expect(@mock.get(key)).to be_nil end + + it 'accepts EXAT seconds' do + expect(@mock.set(key, 1, exat: (@now + 1).to_i)).to eq('OK') + expect(@mock.get(key)).not_to be_nil + allow(Time).to receive(:now).and_return(@now + 2) + expect(@mock.get(key)).to be_nil + end + + it 'accepts PXAT milliseconds' do + expect(@mock.set(key, 1, pxat: ((@now + 500).to_f * 1000).to_i)).to eq('OK') + expect(@mock.get(key)).not_to be_nil + allow(Time).to receive(:now).and_return(@now + 300) + expect(@mock.get(key)).not_to be_nil + allow(Time).to receive(:now).and_return(@now + 600) + expect(@mock.get(key)).to be_nil + end end end end