josiahcarlson / redis-in-action

Example code from the book

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[2.4. Database row caching](https://livebook.manning.com/book/redis-in-action/chapter-2/59) ; 'delay' order set should remove row_id value

zput opened this issue · comments

commented
def schedule_row_cache(conn, row_id, delay):
    conn.zadd('delay:', row_id, delay)           #A
    conn.zadd('schedule:', row_id, time.time())  #39 

def cache_rows(conn):
    while not QUIT:
        next = conn.zrange('schedule:', 0, 0, withscores=True)  #A
        now = time.time()
        if not next or next[0][1] > now:
            time.sleep(.05)                                     #B
            continue

        row_id = next[0][0]
        delay = conn.zscore('delay:', row_id)                   #C
        if delay <= 0:
            conn.zrem('delay:', row_id)                         #D
            conn.zrem('schedule:', row_id)                      #D
            conn.delete('inv:' + row_id)                        #D
            continue

        row = Inventory.get(row_id)                             #E
        conn.zadd('schedule:', row_id, now + delay)             #F
        conn.set('inv:' + row_id, json.dumps(row.to_dict()))    #53 

if i just want to cache one row_id data in 5s.
whether i need to add one line like this:

def cache_rows(conn):
    while not QUIT:
        next = conn.zrange('schedule:', 0, 0, withscores=True)  #A
        now = time.time()
        if not next or next[0][1] > now:
            time.sleep(.05)                                     #B
            continue

        row_id = next[0][0]
        delay = conn.zscore('delay:', row_id)                   #C
        if delay <= 0:
            conn.zrem('delay:', row_id)                         #D
            conn.zrem('schedule:', row_id)                      #D
            conn.delete('inv:' + row_id)                        #D
            continue

        row = Inventory.get(row_id)                             #E
        conn.zadd('schedule:', row_id, now + delay)             #F
        conn.zadd('delay:', row_id, 0)           #  **** I added one line in this ****
        conn.set('inv:' + row_id, json.dumps(row.to_dict()))    #53 

if not, this origin code will loop to cache this row_id corresponding data

I am sorry for not seeing / responding sooner, you are right, this is a bug. Not sure how it passes tests, unless we're not testing it.

Actually looking more in-context, and at your comment, it seems like you are asking a question, not reporting a bug.

If you need this to run for 5 seconds, you can:

def cache_rows(conn, run_for=5):
    end = time.time() + run_for
    while not QUIT and time.time() <= end:
        next = conn.zrange('schedule:', 0, 0, withscores=True)  #A
        now = time.time()
        if not next or next[0][1] > now:
            time.sleep(.05)                                     #B
            continue

        row_id = next[0][0]
        delay = conn.zscore('delay:', row_id)                   #C
        if delay <= 0:
            conn.zrem('delay:', row_id)                         #D
            conn.zrem('schedule:', row_id)                      #D
            conn.delete('inv:' + row_id)                        #D
            continue

        row = Inventory.get(row_id)                             #E
        conn.zadd('schedule:', row_id, now + delay)             #F
        conn.set('inv:' + row_id, json.dumps(row.to_dict()))    #53 

That will ensure that your while loop doesn't run for longer than 5 seconds.