Level 1 Reserve, complete, fail
Build WorkQueue(timeout=None, max_attempts=None). The constructor arguments come in later levels. At this level there are no timeouts and no retry limit.
Every method takes now (an int clock) first. Across calls now never decreases. You can ignore it until level 2.
Each item is in one of four states: "ready", "reserved", "completed" or "dead" (you'll need "dead" from level 3).
enqueue(now, item_id, payload) -> booladds a ready item at the back of the queue. ReturnsFalseand changes nothing if the id has been seen before.reserve(now) -> tuple | Nonetakes the item at the front of the ready queue and marks it reserved. Returns(item_id, payload, token), orNoneif nothing is ready. Thetokenis an opaque value that identifies this particular reservation. Every reservation must get a token that has never been handed out before.complete(now, item_id, token) -> bool: iftokenis the item's current reservation, the item becomes"completed"(a final state) and the call returnsTrue. Otherwise it returnsFalseand changes nothing.fail(now, item_id, token) -> bool: same check. The worker gave up, so the item goes back to the back of the ready queue.state(now, item_id) -> str | Nonereturns the state, orNonefor an unknown id.
q = WorkQueue()
q.enqueue(0, "a", {"n": 1}); q.enqueue(0, "b", {"n": 2})
_, _, ta = q.reserve(1) # ("a", {"n": 1}, <token>)
q.fail(2, "a", ta) # True; the ready order is now b, a
q.complete(3, "a", ta) # False: that reservation is over
q.reserve(4)[0] # "b"
Queue operations and id lookups should be O(1).