Design a Lazily Initialized, Thread-Safe Connection Pool
Context
You are tasked with designing and implementing a connection pool. This pool should manage instances of a given Connection base class, which provides query(...) and close() methods. You can assume that Connection objects are safe to be used by a single thread at a time and that new Connection instances can be created via a provided connection_factory() function.
The core objective is to create a connection pool that initializes connections lazily, reuses them efficiently, handles pool exhaustion gracefully, and ensures thread safety across all operations.
Requirements
You must implement two classes with the following methods:
1. class ConnectionPool
__init__(maxConnectionNum, default_timeout=None): Initializes the connection pool with a maximum number of connections it can manage and an optional default timeout for acquiring connections.getConnection() -> PooledConnection: Retrieves aPooledConnectionwrapper from the pool.close(): Initiates the shutdown of the pool, preventing further connection acquisitions and managing the graceful closure of all underlying connections.
2. class PooledConnection
__init__(parent: ConnectionPool, connection: Connection): Initializes a wrapper for an underlyingConnectioninstance, linked to its parent pool.query(...): Delegates the query operation to the underlyingConnectioninstance.close(): Returns the underlyingConnectionto its parent pool.
Functional Requirements:
- a) Lazy Creation: New
Connectioninstances should only be created whengetConnection()is called and no idle connections are available in the pool. - b) Reuse-First Policy: Prioritize reusing existing idle connections. If no idle connections are available, and the total number of active connections (in-use + idle) is below
maxConnectionNum, a newConnectionshould be created. - c) Exhaustion Policy: When the pool is exhausted (all
maxConnectionNumconnections are in use),getConnection()must adhere to the following:- If
default_timeoutisNone, block indefinitely until a connection becomes available. - If
default_timeoutis specified, block for up to that duration. If a connection is not available within the timeout, raise a timeout error.
- If
- d) Closing Semantics:
PooledConnection.close(): This method must return the underlyingConnectioninstance to the pool for reuse, rather than closing the actual resource.ConnectionPool.close(): This method must prevent any future calls togetConnection()from succeeding. It should immediately close all currently idle connections. For connections that are currently in use, it must ensure they are closed as they are returned to the pool. TheConnectionPool.close()method may block until all borrowed connections have been returned and closed.
- e) Concurrency Safety: The entire connection pool must be thread-safe for concurrent callers. You must discuss and utilize appropriate synchronization primitives to prevent issues such as double-returning the same connection or resource leaks.
Additional Deliverables:
- Clearly describe the core data structures used within the
ConnectionPool. - Analyze and provide the time and space complexity for the
getConnection()andclose()methods.
AI interview prep
Core dilemma
Balancing thread safety and efficient resource management (lazy creation, reuse, exhaustion) with minimal contention, deadlocks, and proper graceful shutdown.
3 tradeoffs and 3 stress tests locked
Interview prep
Unlock the interviewer X-Ray rubric, tradeoff matrix, stress tests, clarifying questions, and key concepts.
Design a Lazily Initialized, Thread-Safe Connection Pool
Context
You are tasked with designing and implementing a connection pool. This pool should manage instances of a given Connection base class, which provides query(...) and close() methods. You can assume that Connection objects are safe to be used by a single thread at a time and that new Connection instances can be created via a provided connection_factory() function.
The core objective is to create a connection pool that initializes connections lazily, reuses them efficiently, handles pool exhaustion gracefully, and ensures thread safety across all operations.
Requirements
You must implement two classes with the following methods:
1. class ConnectionPool
__init__(maxConnectionNum, default_timeout=None): Initializes the connection pool with a maximum number of connections it can manage and an optional default timeout for acquiring connections.getConnection() -> PooledConnection: Retrieves aPooledConnectionwrapper from the pool.close(): Initiates the shutdown of the pool, preventing further connection acquisitions and managing the graceful closure of all underlying connections.
2. class PooledConnection
__init__(parent: ConnectionPool, connection: Connection): Initializes a wrapper for an underlyingConnectioninstance, linked to its parent pool.query(...): Delegates the query operation to the underlyingConnectioninstance.close(): Returns the underlyingConnectionto its parent pool.
Functional Requirements:
- a) Lazy Creation: New
Connectioninstances should only be created whengetConnection()is called and no idle connections are available in the pool. - b) Reuse-First Policy: Prioritize reusing existing idle connections. If no idle connections are available, and the total number of active connections (in-use + idle) is below
maxConnectionNum, a newConnectionshould be created. - c) Exhaustion Policy: When the pool is exhausted (all
maxConnectionNumconnections are in use),getConnection()must adhere to the following:- If
default_timeoutisNone, block indefinitely until a connection becomes available. - If
default_timeoutis specified, block for up to that duration. If a connection is not available within the timeout, raise a timeout error.
- If
- d) Closing Semantics:
PooledConnection.close(): This method must return the underlyingConnectioninstance to the pool for reuse, rather than closing the actual resource.ConnectionPool.close(): This method must prevent any future calls togetConnection()from succeeding. It should immediately close all currently idle connections. For connections that are currently in use, it must ensure they are closed as they are returned to the pool. TheConnectionPool.close()method may block until all borrowed connections have been returned and closed.
- e) Concurrency Safety: The entire connection pool must be thread-safe for concurrent callers. You must discuss and utilize appropriate synchronization primitives to prevent issues such as double-returning the same connection or resource leaks.
Additional Deliverables:
- Clearly describe the core data structures used within the
ConnectionPool. - Analyze and provide the time and space complexity for the
getConnection()andclose()methods.