Implement a Transactional Key-Value Store
Company: Grammarly
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Quick Answer: This question evaluates understanding of transactional state management, data structure design, and consistency/visibility semantics in an in-memory key-value store that supports nested transactions.
Constraints
- 0 <= len(operations) <= 2 * 10^5
- Keys are strings; values are hashable scalars and will not be None
Examples
Input: [('set', 'a', 10), ('set', 'b', 10), ('count', 10), ('begin',), ('set', 'a', 20), ('get', 'a'), ('count', 10), ('count', 20), ('begin',), ('set', 'b', 20), ('count', 20), ('rollback',), ('get', 'b'), ('count', 20), ('commit',), ('get', 'a'), ('get', 'b')]
Expected Output: [2, 20, 1, 1, 2, True, 10, 1, True, 20, 10]
Explanation: After changing a inside a transaction, counts reflect the visible state. The inner transaction changes b, then rollback restores b to 10. commit persists the remaining open transaction, so a stays 20.
Input: [('get', 'x'), ('count', 5), ('rollback',), ('commit',), ('set', 'x', 5), ('get', 'x'), ('count', 5)]
Expected Output: [None, 0, False, False, 5, 1]
Explanation: Missing keys return None, counting an unseen value returns 0, and commit/rollback with no open transaction return False.
Input: [('set', 'k', 1), ('begin',), ('set', 'k', 2), ('set', 'k', 3), ('count', 1), ('count', 3), ('rollback',), ('get', 'k'), ('begin',), ('set', 'k', 4), ('begin',), ('set', 'k', 5), ('rollback',), ('get', 'k'), ('commit',), ('get', 'k')]
Expected Output: [0, 1, True, 1, True, 4, True, 4]
Explanation: Multiple writes to the same key in one transaction should restore the original value on rollback. Rolling back the inner transaction restores k to 4, and commit then makes that value permanent.
Input: []
Expected Output: []
Explanation: No operations produce no output.
Hints
- Use one hash map for the currently visible value of each key, and another hash map to track how many keys currently map to each value.
- For nested transactions, keep a stack of undo logs. The first time a key changes inside a transaction, record its previous value so rollback can restore it.