perl-redis icon indicating copy to clipboard operation
perl-redis copied to clipboard

multi/exec not handled properly when one of the commands has an error

Open karenetheridge opened this issue 12 years ago • 4 comments

It looks like multi transactions are not handled well when one of the transactions has an error.

from the command line:

redis localhost:6379> flushall
OK
redis localhost:6379> multi
OK
redis localhost:6379> set transaction_key_1 foo
QUEUED
redis localhost:6379> hset transaction_key_1 bar 9
QUEUED
redis localhost:6379> hset transaction_key_2 a 9
QUEUED
redis localhost:6379> exec
1) OK
2) (error) ERR Operation against a key holding the wrong kind of value
3) (integer) 1
redis localhost:6379> keys *
1) "transaction_key_2"
2) "transaction_key_1"
redis localhost:6379> hgetall transaction_key_2
1) "a"
2) "9"
redis localhost:6379> get transaction_key_1
"foo"

yet, using the Redis.pm client:

use strict;
use warnings;

use Redis;
use Data::Dumper;

my $redis = Redis->new(
    server => 'localhost:6379',
);

$redis->flushall;
$redis->multi;
$redis->set('transaction_key_1', 'foo');          # ok
$redis->hset('transaction_key_1', 'bar', '9');    # bad data type
$redis->hset('transaction_key_2', 'a', '9');      # ok

my @result = eval { $redis->exec };
my $e = $@;

print "### exec returned: ", Dumper(\@result);
print "### exception is: ", Dumper($e);
print "### all keys are: ", Dumper([ $redis->keys('*') ]);

print "### transaction_key_1: ", Dumper($redis->get('transaction_key_1'));
print "### transaction_key_2: ", Dumper($redis->hgetall('transaction_key_2'));

gives:

### exec returned: $VAR1 = [];
### exception is: $VAR1 = '[exec] ERR Operation against a key holding the wrong kind of value,  at /home/ad/karene/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0/Redis.pm line 531.
        Redis::__read_response_r(\'Redis=HASH(0x271ff98)\', \'exec\', undef) called at /home/ad/karene/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0/Redis.pm line 499
        Redis::__read_response(\'Redis=HASH(0x271ff98)\', \'exec\', undef) called at /home/ad/karene/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0/Redis.pm line 170
        Redis::wait_all_responses(\'Redis=HASH(0x271ff98)\') called at /home/ad/karene/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0/Redis.pm line 160
        Redis::__run_cmd(\'Redis=HASH(0x271ff98)\', \'exec\', undef, undef, undef) called at /home/ad/karene/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0/Redis.pm line 119
        Redis::__std_cmd(\'Redis=HASH(0x271ff98)\', \'exec\') called at /home/ad/karene/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0/Redis.pm line 96
        Redis::__ANON__(\'Redis=HASH(0x271ff98)\') called at demo.pl line 17
        eval {...} called at demo.pl line 17
';
### all keys are: $VAR1 = [
          '1'
        ];
### transaction_key_1: $VAR1 = 'transaction_key_1';
$VAR2 = 'transaction_key_2';
### transaction_key_2: $VAR1 = 'foo';

The results of the 'keys', 'get', and 'hgetall' commands are being returned to the wrong queries -- the result of the 'keys' command is not returned until the subsequent 'get' is called, and then the 'get' results are returned for the 'hgetall' call.

The documentation leaves it open to the client how to return the results of the 'exec' while also indicating the error -- http://redis.io/topics/transactions -- it might be sane to simply die with the expected error, and not return the results at all -- but all the queries should be executed first, and then the exception should be thrown at the end. This looks to be what happened, given that transaction_key_2 did get updated.. only the internal state was corrupted at the same time.

karenetheridge avatar May 15 '13 22:05 karenetheridge

It looks like $collect_errors needs to be true in __read_response_r for the 'exec' command, but I'm having difficulty so far tracing how this value is set.

karenetheridge avatar May 16 '13 00:05 karenetheridge

I'll be on vacation next week, I'll be able to help with this then.

melo avatar May 16 '13 08:05 melo

Oh my... This should have been fixed long time ago. I'll work on it as soon as possible. I don't think it's too difficult. Thanks for your patience while this gets resolved :)

dams avatar Feb 18 '14 00:02 dams

heh, I'm not actually at that job anymore, but I'm sure the new owners of that code would appreciate the fix anyway ;)

karenetheridge avatar Feb 18 '14 02:02 karenetheridge