Reputation: 1384
I have some software written that uses RethinkDB as a queue system. Items are queued, checked out in a random order, and then marked as completed.
Previously, I used code like this to check out a random item from the queue:
d = list(r.db("software").table("queue").get_all("todo", index="status").sample(1).run(conn))
if not d:
return None # no items available
r.db("software").table("queue").get(d[0]['id']).update(
{"status": "claims", "claimed_at": time.time()}
).run(conn)
return d[0]
The problem is that when multiple clients are in use, in the time between getting the item and switching its status to "claims" it is possible for another client to check out the same item. To get around this issue, I added a global lock to the server that is acquired whenever accessing the database. However, this limits performance substantially on slower hosts.
I came up with this code to replace it, which combines it all into a single database query:
result = r.db("software").table("queue").get_all("todo", index="status").sample(1) \
.update({"status": "claims", "claimed_at": time.time()}, return_changes=True).run(conn)
changes = result['changes']
if not changes:
return None # no items available
return changes[0]['old_val']
I have two questions about this new code:
Upvotes: 0
Views: 33