From 505395d3a5e66150aa186ad1f1bd673d7e275b9d Mon Sep 17 00:00:00 2001 From: alexisHetic Date: Mon, 16 Jul 2018 18:06:19 +0200 Subject: [PATCH] Unlock redis for unsuccessful HTTP status --- lib/idempotent-request/redis_storage.rb | 4 ++++ lib/idempotent-request/request_manager.rb | 13 +++++++++++-- spec/idempotent-request/redis_storage_spec.rb | 15 +++++++++++++++ spec/idempotent-request/request_manager_spec.rb | 12 ++++++++++++ spec/support/memory_storage.rb | 6 ++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/idempotent-request/redis_storage.rb b/lib/idempotent-request/redis_storage.rb index 5c029c2..551d7e7 100644 --- a/lib/idempotent-request/redis_storage.rb +++ b/lib/idempotent-request/redis_storage.rb @@ -12,6 +12,10 @@ module IdempotentRequest setnx_with_expiration(lock_key(key), true) end + def unlock(key) + redis.del(lock_key(key)) + end + def read(key) redis.get(namespaced_key(key)) end diff --git a/lib/idempotent-request/request_manager.rb b/lib/idempotent-request/request_manager.rb index b56be8d..c603c15 100644 --- a/lib/idempotent-request/request_manager.rb +++ b/lib/idempotent-request/request_manager.rb @@ -12,6 +12,10 @@ module IdempotentRequest storage.lock(key) end + def unlock + storage.unlock(key) + end + def read status, headers, response = parse_data(storage.read(key)).values @@ -23,8 +27,13 @@ module IdempotentRequest def write(*data) status, headers, response = data response = response.body if response.respond_to?(:body) - return data unless (200..226).include?(status) - storage.write(key, payload(status, headers, response)) + + if (200..226).cover?(status) + storage.write(key, payload(status, headers, response)) + else + unlock + end + data end diff --git a/spec/idempotent-request/redis_storage_spec.rb b/spec/idempotent-request/redis_storage_spec.rb index d338bbb..5d4e853 100644 --- a/spec/idempotent-request/redis_storage_spec.rb +++ b/spec/idempotent-request/redis_storage_spec.rb @@ -23,6 +23,21 @@ RSpec.describe IdempotentRequest::RedisStorage do end end + describe '#unlock' do + let(:key) { 'key' } + let(:lock_key) { "#{namespace}:lock:#{key}" } + + before { redis_storage.lock(key) } + + it 'should unlock' do + expect(redis).to receive(:del).with(lock_key).and_call_original + + redis_storage.unlock(key) + + expect(redis_storage.read(key)).to be_nil + end + end + describe '#write' do let(:key) { 'key' } let(:payload) { {} } diff --git a/spec/idempotent-request/request_manager_spec.rb b/spec/idempotent-request/request_manager_spec.rb index 5b30b23..0550f8d 100644 --- a/spec/idempotent-request/request_manager_spec.rb +++ b/spec/idempotent-request/request_manager_spec.rb @@ -36,6 +36,13 @@ RSpec.describe IdempotentRequest::RequestManager do end end + describe '#unlock' do + it 'delegates to storage service' do + expect(memory_storage).to receive(:unlock).with(request.key) + request_storage.unlock + end + end + describe '#read' do context 'when there is no data' do it 'should return nil' do @@ -137,6 +144,11 @@ RSpec.describe IdempotentRequest::RequestManager do request_storage.write(*data) expect(memory_storage.read(request.key)).to be_nil end + + it 'should unlock stored key' do + expect(memory_storage).to receive(:unlock).with(request.key) + request_storage.write(*data) + end end end diff --git a/spec/support/memory_storage.rb b/spec/support/memory_storage.rb index 8295f7a..727b5a7 100644 --- a/spec/support/memory_storage.rb +++ b/spec/support/memory_storage.rb @@ -10,6 +10,12 @@ module IdempotentRequest @memory[namespaced_key] = true end + def unlock(key) + namespaced_key = lock_key(key) + @memory.delete(namespaced_key) + @memory[namespaced_key] + end + def read(key) @memory[key] end