A practice prompt we wrote. No company or candidate report names it, so it carries no company tag.

How to answer

A priority heap is quick. Spend the time on what happens when a job or a worker fails.

  1. Pin the interface and the promise. “enqueue(payload, priority), lease() returns a job and token, ack(id, token), nack(id, token, error). Lower numbers run first, first in first out within a priority.” Then say the delivery promise: at least once. A worker can finish the work and die before it acks, so handlers must be safe to run twice.
  2. Choose the structures aloud. A heap of (priority, seq, job_id): the counter keeps FIFO order within a priority, and holding the id rather than the payload means the heap never compares payloads. A second heap holds retries waiting out their backoff, keyed by ready time. A third holds lease deadlines. Stale heap entries are skipped when popped, not removed from the middle, so each heap operation stays O(log n).
  3. Count an attempt when the job is handed out. A job that crashes its worker never calls nack. If only failures count, it loops forever.
  4. Make leases expire, and check tokens. An expired lease returns the job to the queue. The late worker’s ack must then be refused, or it deletes a job another worker is running.
  5. Bound the retries, then keep the evidence. Back off between attempts, stop at a limit, and move the job to the dead-letter list with every error and its time. Offer a redrive for after the cause is fixed.
  6. Test with a fake clock. Priority order, backoff, a lease timeout, a stale ack and a poison job that ends in dead letters, all without sleeping.

The trap is a dead-letter list that holds only job ids. Whoever reads it needs the payload, the attempts and the errors to decide whether a replay is safe.

Follow-ups

What the interviewer may ask next, once your first answer is on the table.

  • A worker finishes the job, then dies before it acks. What happens, and what does that demand of the job handler?
  • High-priority work arrives all day and low-priority jobs never run. What do you change?
  • The queue has to survive a restart and serve workers on several machines. What replaces each structure?
  • Someone on the customer’s team finds a job in the dead-letter list. What do they need to see to decide whether to replay it?
  • A job legitimately takes ten minutes and the lease is thirty seconds. How does the worker keep it?

Where answers go wrong

  • Pushing tuples of priority and payload onto a heap, so equal priorities lose their order and two dict payloads raise a TypeError.
  • Counting attempts only on an explicit failure, so a job that crashes its worker never reaches the dead-letter list and loops forever.
  • Accepting an ack without a lease token, so a worker whose lease expired deletes a job that another worker is running.

Answer this in two minutes

Write the answer you would say out loud. The clock starts with your first word.

Two minutes

Model answer

“I’ll use three heaps and a dict of jobs by id, all behind one lock. The clock and the backoff are parameters so the tests never sleep.”