gns_ua: (russe)
gns_ua ([personal profile] gns_ua) wrote2013-01-15 10:09 am

(no subject)

Вот оно чо.

[altlinux@eeelive ~]$ python -c 'import redis, time; r=redis.Redis(); p=r.pipeline(); p.watch("abc"); p.set("123", 1); time.sleep(5); p.execute()'

В monitor видно, что херню делает:

1358237927.046987 [0 127.0.0.1:51442] "WATCH" "abc"
1358237927.048088 [0 127.0.0.1:51442] "SET" "123" "1"
1358237932.053436 [0 127.0.0.1:51442] "MULTI"
1358237932.053582 [0 127.0.0.1:51442] "EXEC"
1358237932.054853 [0 127.0.0.1:51442] "UNWATCH"


Зато вот такое, без вотча:

$ python -c 'import redis, time; r=redis.Redis(); p=r.pipeline(); p.set("123", 1);time.sleep(2); p.execute()'

Делает:

1358237753.861087 [0 127.0.0.1:51420] "MULTI"
1358237753.861234 [0 127.0.0.1:51420] "SET" "123" "1"
1358237753.861319 [0 127.0.0.1:51420] "EXEC"


Всё правильно. Тогда какого?

Можно сперва запайпить, а потом уж ставить вотч и экзекать. Это работает:

$ python -c 'import redis, time; r=redis.Redis(); print r.get("abc"); p=r.pipeline(); p.set("abc", 1); p.watch("abc"); time.sleep(5); p.execute(); print r.get("abc");'
None
1
===============================
1358238142.575640 [0 127.0.0.1:51474] "GET" "abc"
1358238142.577093 [0 127.0.0.1:51474] "WATCH" "abc"
1358238147.579733 [0 127.0.0.1:51474] "MULTI"
1358238147.579892 [0 127.0.0.1:51474] "SET" "abc" "1"
1358238147.579977 [0 127.0.0.1:51474] "EXEC"
1358238147.581572 [0 127.0.0.1:51474] "UNWATCH"
1358238147.582558 [0 127.0.0.1:51474] "GET" "abc"


И я бы даже смирился, да вот беда - их собственный враппер делает сначала watch, а потом отдаёт пайп для работы:

    def transaction(self, func, *watches, **kwargs):
        """
        Convenience method for executing the callable `func` as a transaction
        while watching all keys specified in `watches`. The 'func' callable
        should expect a single arguement which is a Pipeline object.
        """
        shard_hint = kwargs.pop('shard_hint', None)
        with self.pipeline(True, shard_hint) as pipe:
            while 1:
                try:
                    if watches:
                        print "Watching %s" % watches
                        pipe.watch(*watches)
                    func(pipe)
                    return pipe.execute()
                except WatchError:
                    import traceback
                    traceback.print_exc()
                    continue


В то время как в Pipeline прямо написано:

    def execute_command(self, *args, **kwargs):
        if (self.watching or args[0] == 'WATCH') and \
                not self.explicit_transaction:
            return self.immediate_execute_command(*args, **kwargs)
        return self.pipeline_execute_command(*args, **kwargs)


Т.е. если поставил вотч, все следующие команды выполняются напрямую! И можно ещё воспользоваться explicit transaction и сказать p.multi(), тока вот опять же их собственный враппер не таков.

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting