Implement a Stateful Chatter Message Store
RedditSoftware Engineer · Technical ScreenLast updated
Design and implement an in-memory message store supporting batch appends, contextual neighborhood queries, text editing with history tracking, and interval merging for read operations.
Problem Statement
In real-time chat platforms, message services need to store chronologically ordered messages, retrieve surrounding message contexts for rendering, track message revisions without losing history, and merge overlapping range fetches to minimize redundant reads.
Implement the ChatterStore class with the following methods:
__init__(): Initializes an empty message store.append_batch(messages: list[tuple[int, str]]) -> None: Ingests a batch of messages. Each message is a tuple of(id, text). Incoming batches are guaranteed to be sorted in strictly ascending order byid, and all IDs in the batch are strictly greater than any previously ingested ID.edit_message(message_id: int, new_text: str) -> bool: Updates the message text tonew_textand records the edit history. ReturnsTrueif the message exists, orFalseifmessage_idis not found.get_neighborhood(message_id: int, k_before: int, k_after: int) -> list[tuple[int, str]] | None: Returns up tok_beforemessages immediately precedingmessage_id, the target message itself (with its current text), and up tok_aftermessages immediately followingmessage_id, in ascending order of ID. ReturnsNoneifmessage_iddoes not exist.merge_read_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]: Merges a list of closed message ID intervals[start_id, end_id]such that overlapping or directly adjacent intervals (e.g.,[1, 5]and[6, 10]) are combined into a single consolidated interval. The output must be sorted in ascending order of start IDs.
Input & Output Format
messages: A list of tuples(id: int, text: str).intervals: A list of tuples(start_id: int, end_id: int)wherestart_id <= end_id.get_neighborhood: Returns a list of(id, current_text)tuples, orNone.
Constraints
1 <= id <= 10^12(IDs can be 64-bit integers).1 <= len(text) <= 1000.- Total messages stored across all calls
<= 2 * 10^5. 0 <= k_before, k_after <= 100.intervalslength<= 10^4.- All method calls except
merge_read_intervalsshould run inO(1)orO(log N + k)time, whereNis the total message count andk = k_before + k_after.
Example
store = ChatterStore()
store.append_batch([(10, "hello"), (20, "world"), (30, "foo"), (40, "bar")])
# Context query around ID 20 with 1 before and 1 after
assert store.get_neighborhood(20, 1, 1) == [(10, "hello"), (20, "world"), (30, "foo")]
# Edit a message
assert store.edit_message(20, "everyone") == True
assert store.get_neighborhood(20, 0, 1) == [(20, "everyone"), (30, "foo")]
# Non-existent ID
assert store.get_neighborhood(99, 1, 1) is None
assert store.edit_message(99, "test") == False
# Merge read intervals
raw_intervals = [(10, 20), (30, 45), (21, 25), (40, 50)]
assert store.merge_read_intervals(raw_intervals) == [(10, 25), (30, 50)]
Edge Cases
- Boundaries for neighborhood lookups: requesting more before/after items than exist in the store should return as many available items as possible without error.
k_beforeork_afterequal to 0.- Adjacent discrete intervals like
[1, 5]and[6, 10]must be merged into[1, 10]because discrete IDs leave no gap in between.
Hints
Hint 1
Use a list to store message order along with a hash map mapping each message ID to its list index for O(1) random access and index-based slicing.
Hint 2
For the neighborhood query, clamp index boundaries between 0 and the current length of the message array to avoid index out-of-bounds errors.
Hint 3
When merging discrete integer intervals, two intervals `[a, b]` and `[c, d]` can be combined if `c <= b + 1`.
Follow-up questions
- How would you extend this design to support point-in-time snapshot reads (e.g., retrieving the neighborhood as it existed at version T)?
- If IDs were non-contiguous 64-bit integers and messages could arrive out of order, what data structure would maintain ordered lookups efficiently?
- How would you handle thread safety if multiple threads append and edit concurrently while readers query neighborhoods?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.