Katkat

Dispatch Parcels to Delivery Drones That May Go Silent Mid-Flight

OpenAISoftware Engineer · Technical Screen

Last updated

Build an in-process dispatcher that hands delivery parcels to drones, reclaims a parcel when its drone goes silent, rejects stale reports from a drone that already lost its parcel, and quarantines parcels that fail too many times.

A dispatch center hands out delivery parcels to drones. A drone can lose its radio link, crash, or explicitly radio back a failure at any point after it picks up a parcel. The dispatcher must guarantee that no parcel silently disappears: every submitted parcel is eventually delivered by some drone, or is deliberately set aside after it keeps failing.

Design the dispatcher as a class and implement it with runnable code, plus tests that simulate drones going silent.

Requirements

  • submit(parcel_id, payload) — queue a new parcel for delivery.
  • assign(drone_id, now) — hand the next pending parcel to a drone, starting a time-boxed lease. Returns None if nothing is pending.
  • heartbeat(parcel_id, token, now) — a drone still in flight extends its lease.
  • complete(parcel_id, token, now) — a drone reports successful delivery.
  • fail(parcel_id, token, now) — a drone explicitly reports it could not deliver.
  • Any lease that expires without a heartbeat, completion, or failure must be treated as the drone going silent: the parcel is reclaimed and reassigned.
  • A drone that was presumed lost and later calls heartbeat, complete, or fail with its old token must be rejected — its parcel may already be with a different drone.
  • A parcel that fails (explicitly or by timeout) max_attempts times total is moved to a dead-letter set instead of being retried again.
  • The dispatcher is called concurrently from multiple threads and must stay consistent.
  • Tests must be deterministic: control time explicitly rather than depending on the wall clock.

Example

submit("parcel-1", {...})
assign("drone-X", now=0)        -> ("parcel-1", token=1, payload)
heartbeat("parcel-1", token=1, now=5)   -> True   (lease extended)
# drone-X goes silent; its lease expires
assign("drone-Y", now=16)       -> ("parcel-1", token=2, payload)   (reclaimed)
complete("parcel-1", token=1, now=17)   -> False  (stale token, drone-X was replaced)
complete("parcel-1", token=2, now=18)   -> True   (drone-Y is the current holder)

Constraints

  • Treat this as an in-process data structure (no real network or real drones).
  • State clearly what "at least once" vs. "exactly once" means for your design, and which one you deliver.

Hints

Hint 1

A parcel that has been handed out but not yet confirmed still needs a record in the dispatcher — decide what that record holds and until when it lives.

Hint 2

Pass `now` explicitly into every call instead of reading the wall clock, so tests can simulate the passage of time deterministically.

Hint 3

Give every assignment a unique token (or generation number). When a drone reports back, compare its token against the parcel's current token before accepting the report.

Hint 4

A single lock around all state mutations is simpler and safe enough here than fine-grained locking — profile before reaching for anything fancier.

Follow-up questions

  • How would you change the design if two parcels could be batched onto one drone trip?
  • What happens if the dispatcher process itself crashes and restarts — what state would you need to persist?
  • How would you expose metrics like average lease extensions per parcel or dead-letter rate?
  • Could you make delivery exactly-once instead of at-least-once, and what would it cost?