Home/Low-level design/Message Broker

Message Broker

Independent delivery state and bounded retries

Retained messages and group progress are separate state. A group starts at the oldest retained message even when it subscribes late. A poll returning an already in-flight delivery repeats the same attempt; only a retry after rejection increments it.

cpp
struct Progress {std::size_t offset=0;Int attempt=0;bool inflight=false;};
// ack is valid only while inflight, not between nack and redelivery.

Keep lifetime message-ID uniqueness independent of consumption and group offsets. Advancing one group must not consume another group's message. At the attempt limit, append one group-specific dead letter and advance that group's offset exactly once. Returning copies prevents a consumer changing retained payloads or delivery counters. No automatic timeout exists: retry transitions happen only through nack and a subsequent poll. These state transitions are deterministic without networking, threads, or sleeping.

C++ contract conventions: numeric values use signed Int (long long); all inputs and intermediate arithmetic are within its representable range. Opt<T> means std::optional<T> and absence is std::nullopt; Vec<T> means std::vector<T>. Invalid documented arguments throw std::invalid_argument. Inputs passed by const reference remain caller owned. Returned containers and records own their contents. Calls use the declared C++ parameter types. Implicit conversions performed by the caller are outside the runtime validation contract. Unless a lesson states otherwise, string ordering is lexicographic over Unicode code points (Text) or UTF-8 identifiers (std::string).

Put it into practice

Implement the exercise in a full-screen workspace, then run its tests.

Open practice
Next lessonFile Storage System