Skip to content
BytePatterns

Visibility Timeouts in a Message Queue

MediumSystem Design#message-queue#event-simulation~25m

Problem

A queue hands each message to one consumer at a time. When a consumer polls at time t, it receives the first message, in the order they were sent, that is currently visible. A received message is hidden for timeout seconds. If the consumer's processing time is shorter than the timeout, it acknowledges in time and the message is deleted. Otherwise the message becomes visible again at t + timeout, and once it has been received max_receives times without an acknowledgement it moves to a dead-letter queue instead. Given the messages, the polls as (time, consumer) sorted by time, and each consumer's processing time, return the delivery log as (time, consumer, message or None), the messages completed in order, and the dead-lettered messages.

Examples

Input:  messages = ["m1", "m2"], polls = [(0, "slow"), (1, "fast"), (30, "fast"), (31, "fast")],
        work = {"slow": 60, "fast": 2}, timeout = 30, max_receives = 3
Output: ([(0, 'slow', 'm1'), (1, 'fast', 'm2'), (30, 'fast', 'm1'), (31, 'fast', None)], ['m2', 'm1'], [])
Why:    slow cannot finish m1 within 30 seconds, so m1 reappears at 30 and fast picks it up
Input:  messages = ["poison"], polls at 0, 10, 20 and 30 by "a", work = {"a": 99}, timeout = 10, max_receives = 3
Output: ([(0, 'a', 'poison'), (10, 'a', 'poison'), (20, 'a', 'poison'), (30, 'a', None)], [], ['poison'])
Why:    a message that always fails is parked after 3 tries instead of blocking the queue forever
Input:  messages = [], polls = [(5, "a")], work = {"a": 1}, timeout = 10, max_receives = 3
Output: ([(5, 'a', None)], [], [])
Why:    edge case, polling an empty queue returns nothing

Hints

0 / 3

Stuck on the idea rather than the code? Message Queues covers it.