49. Design a Connection Pool with an Internal Request Queue

Design a Connection Pool with an Internal Request Queue
Design an in-memory Connection Pool that maintains a fixed number of reusable connection objects.

Connections are indexed as integers: 0, 1, 2, ... capacity - 1.

Clients requests a connection using a requestId. If a free connection exists, it is assigned immediately. If no free connection exists, the request is placed into an internal queue and will wait until a connection becomes free.

The internal queue is FIFO (first-come-first-serve): whenever a connection is released, it is immediately assigned to the oldest queued request.

Method Signatures

  • Constructor: ConnectionPool(int capacity)
    • capacity is always between 1 and 5000.

  • Acquire: int acquireConnection(String requestId)
    • requestId is always non-empty and unique. It contains only characters from [a-z] and [0-9].
    • acquireConnection will never be called with a duplicate requestId.
    • If a connection is available, assign it to the request and return its connectionId.
    • If multiple connections are available, assign the connection with the lowest index.
    • If all connections are blocked, enqueue the request and return -1. The request will be assigned a connection later when one becomes free.

  • Release: boolean releaseConnection(String requestId)
    • Return true if requestId is valid and currently holds a connection, and that connection is released.
    • Otherwise, return false.
    • As soon as a connection is released, it is immediately assigned to the oldest request waiting in the internal queue (if any).

  • Expire: void expireRequest(String requestId)
    • If requestId is present in the internal request queue, remove it. No connection will ever be assigned to it.
    • If the request is not in the queue or is currently holding a connection, do nothing.

  • Query: List<String> getRequestsWithConnection()
    • Return a list of all requests that are currently holding a connection, along with the connection id.
    • Each item must be formatted as: "requestId-connectionId" (e.g. "request12-4").
    • The list must be sorted in lexicographically ascending order by requestId.

Examples

Example 1: Acquire when connections are free


ConnectionPool pool = new ConnectionPool(3);   // connections: 0,1,2

pool.acquireConnection("a1");  // returns 0
pool.acquireConnection("a2");  // returns 1
pool.acquireConnection("a3");  // returns 2

pool.getRequestsWithConnection();  // ["a1-0", "a2-1", "a3-2"]
        

Example 2: Queue requests when pool is full, then assign on release (FIFO)


ConnectionPool pool = new ConnectionPool(2);   // connections: 0,1

pool.acquireConnection("a1");  // returns 0
pool.acquireConnection("a2");  // returns 1

pool.acquireConnection("b1");  // returns -1 (queued)
pool.acquireConnection("b2");  // returns -1 (queued)

pool.releaseConnection("a1");  // returns true
// connection 0 is immediately assigned to oldest queued request "b1"

pool.getRequestsWithConnection();  // ["a2-1", "b1-0"]
        

Example 3: Expire a queued request


ConnectionPool pool = new ConnectionPool(1);   // connection: 0

pool.acquireConnection("a1");  // returns 0
pool.acquireConnection("b1");  // returns -1 (queued)
pool.acquireConnection("b2");  // returns -1 (queued)

pool.expireRequest("b1");      // b1 removed from queue

pool.releaseConnection("a1");  // returns true
// connection 0 is assigned to oldest remaining queued request "b2"

pool.getRequestsWithConnection();  // ["b2-0"]
        

Example 4: Invalid release


ConnectionPool pool = new ConnectionPool(1);

pool.releaseConnection("x1");       // false (unknown request)
pool.acquireConnection("a1");       // 0
pool.releaseConnection("a1");       // true
pool.releaseConnection("a1");       // false (already released, not holding now)
        




Please use Laptop/Desktop or any other large screen to add/edit code.