Implement a Database Connection Pool
Company: Harvey
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Quick Answer: This question evaluates skills in concurrent resource management, synchronization primitives, and robust connection lifecycle handling within database connectivity and systems programming.
Constraints
- 1 <= max_connections <= 100000
- 0 <= len(operations) <= 200000
- request_id contains no ':' or ';' characters
- The only operation names are 'acquire', 'release', 'timeout', and 'shutdown'
- All operations are processed sequentially in the given order, representing a thread-safe serialization of concurrent requests
Examples
Input: (2, [('acquire', 'A'), ('acquire', 'B'), ('release', 'A'), ('acquire', 'C'), ('release', 'B'), ('release', 'C')])
Expected Output: ['acquired:A:1', 'acquired:B:2', 'released:A', 'acquired:C:1', 'released:B', 'released:C']
Explanation: A and B create connections 1 and 2. After A releases connection 1, C reuses that idle connection.
Input: (2, [('acquire', 'A'), ('acquire', 'B'), ('acquire', 'C'), ('acquire', 'D'), ('release', 'B'), ('release', 'A'), ('release', 'C'), ('release', 'D')])
Expected Output: ['acquired:A:1', 'acquired:B:2', 'waiting:C', 'waiting:D', 'released:B;acquired:C:2', 'released:A;acquired:D:1', 'released:C', 'released:D']
Explanation: The pool reaches capacity after A and B. C and D wait in FIFO order. Releasing B wakes C, and releasing A wakes D.
Input: (1, [('release', 'A'), ('acquire', 'A'), ('acquire', 'A'), ('acquire', 'B'), ('release', 'B'), ('release', 'A'), ('release', 'A'), ('release', 'B')])
Expected Output: ['invalid_release:A', 'acquired:A:1', 'invalid_acquire:A', 'waiting:B', 'invalid_release:B', 'released:A;acquired:B:1', 'invalid_release:A', 'released:B']
Explanation: A cannot release before acquiring, cannot acquire twice while holding, and cannot release twice. B cannot release while it is only waiting.
Input: (1, [('acquire', 'A'), ('acquire', 'B'), ('acquire', 'C'), ('timeout', 'B'), ('release', 'A'), ('timeout', 'B'), ('release', 'C')])
Expected Output: ['acquired:A:1', 'waiting:B', 'waiting:C', 'timed_out:B', 'released:A;acquired:C:1', 'invalid_timeout:B', 'released:C']
Explanation: B times out while waiting, so when A releases the connection, the pool skips B and hands the connection to C.
Input: (2, [('acquire', 'A'), ('acquire', 'B'), ('acquire', 'C'), ('shutdown',), ('acquire', 'D'), ('release', 'A'), ('release', 'C'), ('release', 'B'), ('release', 'A')])
Expected Output: ['acquired:A:1', 'acquired:B:2', 'waiting:C', 'shutdown:1', 'rejected:D', 'released:A', 'invalid_release:C', 'released:B', 'invalid_release:A']
Explanation: Shutdown cancels the one pending waiter C and rejects new acquire D. Existing holders A and B can still release, but C no longer owns or waits for a connection.
Input: (3, [])
Expected Output: []
Explanation: With no operations, the pool produces no log entries.
Hints
- Track three groups separately: idle connections, current owners, and waiting requests.
- A FIFO queue handles waiters, but timeouts may leave stale entries. Consider a set to know which queued requests are still actually waiting.