From 61c36e02373c9317b042723f574cda6791c6f70f Mon Sep 17 00:00:00 2001 From: Timothy Cardenas Date: Thu, 10 Sep 2020 13:06:10 -0700 Subject: [PATCH] fix: corruption of client during interrupt --- lib/redis.rb | 20 +++++++++----------- test/pipelining_commands_test.rb | 7 +++++++ test/transactions_test.rb | 7 +++++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/redis.rb b/lib/redis.rb index 1e9a231d3..8410ac8b6 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -2438,14 +2438,13 @@ def unwatch end def pipelined - synchronize do |_client| + synchronize do |prior_client| begin - pipeline = Pipeline.new(@client) - original, @client = @client, pipeline + @client = Pipeline.new(prior_client) yield(self) - original.call_pipeline(@client) + prior_client.call_pipeline(@client) ensure - @client = original + @client = prior_client end end end @@ -2481,17 +2480,16 @@ def pipelined # @see #watch # @see #unwatch def multi - synchronize do |client| + synchronize do |prior_client| if !block_given? - client.call([:multi]) + prior_client.call([:multi]) else begin - pipeline = Pipeline::Multi.new(@client) - original, @client = @client, pipeline + @client = Pipeline::Multi.new(prior_client) yield(self) - original.call_pipeline(pipeline) + prior_client.call_pipeline(@client) ensure - @client = original + @client = prior_client end end end diff --git a/test/pipelining_commands_test.rb b/test/pipelining_commands_test.rb index 9f2afea8b..be5243b85 100644 --- a/test/pipelining_commands_test.rb +++ b/test/pipelining_commands_test.rb @@ -252,4 +252,11 @@ def test_nested_pipeline_select_client_db assert_equal 3, r._client.db end + + def test_pipeline_interrupt_preserves_client + original = r._client + Redis::Pipeline.stubs(:new).raises(Interrupt) + assert_raises(Interrupt) { r.pipelined {} } + assert_equal r._client, original + end end diff --git a/test/transactions_test.rb b/test/transactions_test.rb index 264e1f364..fd76af634 100644 --- a/test/transactions_test.rb +++ b/test/transactions_test.rb @@ -196,6 +196,13 @@ def test_multi_with_a_block_yielding_the_client assert_equal "s1", r.get("foo") end + def test_multi_with_interrupt_preserves_client + original = r._client + Redis::Pipeline.stubs(:new).raises(Interrupt) + assert_raises(Interrupt) { r.multi {} } + assert_equal r._client, original + end + def test_raise_command_error_when_exec_fails redis_mock(exec: ->(*_) { "-ERROR" }) do |redis| assert_raises(Redis::CommandError) do