Coding questions · Meta
Implement a versioned in-memory DB with CAS and history
This question evaluates a candidate's ability to design and implement time-versioned in-memory data structures, conditional concurrency primitives (compare-and-set and compare-and-delete), TTL expiration semantics, and efficient historical reads.
In-Memory DB V2: TTL + Compare-And-Set/Delete + Historical Reads
Implement an in-memory database keyed by (key, field) supporting TTL, conditional updates, scans, and historical queries.
Data model / rules
- For each
(key, field)store:valueexpire_at(integer;+∞means never expires)
- A record is visible at time
tifft < expire_at. - All operations are given a
timestamp. You may assume operations are provided in non-decreasing timestamp order. - You must also support historical queries: retrieve what value was valid at some earlier time.
API
-
set(timestamp, key, field, value) -> void- Set with no TTL (
expire_at = +∞).
- Set with no TTL (
-
set_with_ttl(timestamp, key, field, value, ttl) -> void- Set with
expire_at = timestamp + ttl.
- Set with
-
get(timestamp, key, field) -> value | null- Return current value if exists and not expired at
timestamp, elsenull.
- Return current value if exists and not expired at
-
compare_and_set(timestamp, key, field, expected_value, new_value) -> bool- If
(key, field)exists and is not expired attimestampand its current value equalsexpected_value, update it tonew_value(expire_at = +∞) and returntrue. - Otherwise return
false.
- If
-
compare_and_set_with_ttl(timestamp, key, field, expected_value, new_value, ttl) -> bool- Same as above, but sets
expire_at = timestamp + ttl.
- Same as above, but sets
-
compare_and_delete(timestamp, key, field, expected_value) -> bool- If current visible value equals
expected_value, delete it and returntrue, else returnfalse.
- If current visible value equals
-
scan(timestamp, key) -> list<string>- Return all non-expired fields for
keyattimestamp. - Sort by
fieldascending. - Format each item as
"field(value)".
- Return all non-expired fields for
-
scan_by_prefix(timestamp, key, prefix) -> list<string>- Like
scan, but only fields starting withprefix.
- Like
-
get_value_at(timestamp, key, field, at_timestamp) -> value | null- Return the value that was valid for
(key, field)at timeat_timestamp. - Return
nullif it did not exist, was deleted, or was expired atat_timestamp.
- Return the value that was valid for
Notes
- You will likely need to keep a per-(key,field) history of changes to answer
get_value_atefficiently. - Assume up to ~1e5 operations.
Versioned In-Memory DB Operations
Constraints
- Operation timestamps are non-decreasing
Examples
Example 1
Input: ((('set', 1, 'u', 'name', 'Ann'), ('get', 2, 'u', 'name'), ('cas', 3, 'u', 'name', 'Ann', 'Ana'), ('get', 4, 'u', 'name')),)
Output: ['Ann', True, 'Ana']
Explanation: Set, get, compare-and-set.
Example 2
Input: ((('set_ttl', 1, 'k', 'a', 'v', 3), ('get', 3, 'k', 'a'), ('get', 4, 'k', 'a'), ('get_at', 5, 'k', 'a', 2)),)
Output: ['v', None, 'v']
Explanation: TTL visibility and historical read.
Hints
- Keep current state for live reads and append history entries for historical reads.