josiahcarlson/redis-in-action

expire duplication & race condition (exercise from chapter 3)

egoarka opened this issue · 3 comments

Hi there, I have some questions :)

  1. What's point to duplicate expire in chapter 3?

pipeline.expire('voted:' + article_id, int(posted-cutoff)) #B

(already have in post_article from chapter 1)

conn.expire(voted, ONE_WEEK_IN_SECONDS) #B

  1. Exercise from chapter 3: Removing of race conditions

How to actually spot this behavior? I always get expected results with article_vote from chapter1 (running concurrently:
https://github.com/egoarka/redis-in-action-typescript/blob/77dadb7214d4a8bec07c6d8d7217d1070c93939e/src/chapter3/ch3.spot.ts#L24)

execution logs: https://gist.github.com/egoarka/565bc9ade7afdc4158f438b35b5fd8d8

  1. Missed tab?
    conn.zincrby('viewed:', item, -1)
  1. What's point to duplicate expire in chapter 3?

Race conditions. Time can pass between checking the time saying it is okay to vote, and the key being deleted on the server. If you then perform a SADD a few lines later, you've created a set without an expiration time, which will last forever. That EXPIRE call ensures that even if that specific python function got swapped out for a week between comments A and B in the code you linked from chapter 3, we would still get the set expiring eventually. Edit: Also, you should check out the original article_vote() function from chapter 1:

def article_vote(conn, user, article):

  1. Exercise from chapter 3: Removing of race conditions - How to actually spot this behavior?

To spot this behavior you have to think very carefully about what a "race condition" is. A race condition is a swapping of execution contexts at unknown or unexpected times. If you look back at the code from chapter 1 in listing 1.6, we're not using pipelines or MULTI/EXEC at all. We're doing single commands. So... any one of many commands can execute between our operations, and we need to watch out for that.

  1. Missed tab?

None passing through was not intentional, but always keeping a count even on "invalid" items was intentional. So probably missed tab. I'll update the code and errata tomorrow.

Thank you for an explanation! I eventually have grasped it :)

The errata have been updated and the two update_token() indentation bugs have been fixed. Thank you for the questions and the errata!