Skip to content

Commit 07fec7e

Browse files
nickgayaandymccurdy
authored andcommitted
Don't send DISCARD after ExecAbortError in pipeline
The `EXECABORT` error type was added in Redis 2.6.5 and is returned from an `EXEC` command to indicate that the transaction was aborted due to an invalid command. It is not necessary to call `DISCARD` after this error, and doing so causes a "DISCARD without MULTI" error.
1 parent 81d7665 commit 07fec7e

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
during command packing. Thanks @Cody-G. #1265, #1285
1717
* HSET command now can accept multiple pairs. HMSET has been marked as
1818
deprecated now. Thanks to @laixintao #1271
19+
* Don't manually DISCARD when encountering an ExecAbortError.
20+
Thanks @nickgaya, #1300/#1301
1921
* 3.4.1
2022
* Move the username argument in the Redis and Connection classes to the
2123
end of the argument list. This helps those poor souls that specify all

redis/client.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3898,8 +3898,6 @@ def _execute_transaction(self, connection, commands, raise_on_error):
38983898
try:
38993899
response = self.parse_response(connection, '_')
39003900
except ExecAbortError:
3901-
if self.explicit_transaction:
3902-
self.immediate_execute_command('DISCARD')
39033901
if errors:
39043902
raise errors[0][1]
39053903
raise sys.exc_info()[1]

tests/test_pipeline.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ def test_parse_error_raised(self, r):
172172
assert pipe.set('z', 'zzz').execute() == [True]
173173
assert r['z'] == b'zzz'
174174

175+
def test_parse_error_raised_transaction(self, r):
176+
with r.pipeline() as pipe:
177+
pipe.multi()
178+
# the zrem is invalid because we don't pass any keys to it
179+
pipe.set('a', 1).zrem('b').set('b', 2)
180+
with pytest.raises(redis.ResponseError) as ex:
181+
pipe.execute()
182+
183+
assert unicode(ex.value).startswith('Command # 2 (ZREM b) of '
184+
'pipeline caused error: ')
185+
186+
# make sure the pipe was restored to a working state
187+
assert pipe.set('z', 'zzz').execute() == [True]
188+
assert r['z'] == b'zzz'
189+
175190
def test_watch_succeed(self, r):
176191
r['a'] = 1
177192
r['b'] = 2

0 commit comments

Comments
 (0)