rsdrsd
rsdrsd

Reputation: 317

Redis in action example

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.

Upvotes: 4

Views: 3907

Answers (1)

spinlok
spinlok

Reputation: 3661

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

Upvotes: 9

Related Questions