Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis in action example

Tags:

python

redis

From the "Redis in Action" book I was reading I saw the following example and now I'm wondering if this is correct or not. The example has the following code in python:

def purchase_item(conn, buyerid, itemid, sellerid, lprice):
buyer = "users:%s"%buyerid
seller = "users:%s"%sellerid
item = "%s.%s"%(itemid, sellerid)
inventory = "inventory:%s"%buyerid
end = time.time() + 10
pipe = conn.pipeline()


while time.time() < end:
    try:
        pipe.watch("market:", buyer)                #A
        price = pipe.zscore("market:", item)        #B
        funds = int(pipe.hget(buyer, "funds"))      #B
        if price != lprice or price > funds:        #B
            pipe.unwatch()                          #B
            return None


        pipe.multi()                                #C
        pipe.hincrby(seller, "funds", int(price))   #C
        pipe.hincrby(buyer, "funds", int(-price))   #C
        pipe.sadd(inventory, itemid)                #C
        pipe.zrem("market:", item)                  #C
        pipe.execute()                              #C
        return True
    except redis.exceptions.WatchError:             #D
        pass                                        #D


return False

As you can see this example uses pipelining, and from what I have understand, the commands aren't executed until pipe.execute() is called. In this example you see at #B an if statement, but is the price value returned here or not? Or is the code exectution somehow buffered when conn.pipeline() is called.

like image 286
rsdrsd Avatar asked Jan 10 '23 21:01

rsdrsd


1 Answers

I'm assuming you're using the redis-py library. When you call pipe.watch(), the pipeline is put into execution mode with immediate effect. So you're able to use regular python code to check the return values of subsequent commands. You can put the pipeline in buffered mode again, by using pipe.multi() which is exactly what the code is doing. The last pipe.execute() is only to execute the commands marked "#C" in your code. All this is explained in the redis-py docs. To summarize:

pipe.watch(...) # <--- executed immediately
pipe.zscore(...) # <--- executed immediately
.....
pipe.multi() # <--- put pipeline back in *buffered* mode
pipe.incr(..) # <--- buffered command 1
pipe.incr(..) # <--- buffered command 2
pipe.execute() # <--- execute buffered commands 1 and 2
like image 185
spinlok Avatar answered Jan 21 '23 05:01

spinlok