     private let maxPoolSize: UInt
     private var connectionPool: [Connection]
     private var activeConnections: UInt
+    private var poolSemaphore: DispatchSemaphore
     
     static private var activeLock = Lock()
     

    @discardableResult
    public func execute(_ query: String, _ values: [NodeRepresentable] = []) throws -> [[String: Node]] {
        var result = [[String : Node]]()
        var connection: Connection?
        try Database.activeLock.locked {
            let start = Date()
            
            // TODO: Block the caller until a connection becomes available WITHOUT blocking the Database thread

            while connectionPool.isEmpty {
                if activeConnections < maxPoolSize {
                    // Haven't reached limit; create a new connection and add it to the pool
                    let conn = try makeConnection()
                    connectionPool.append(conn)
                }
                // Arbitrary 20-second timeout
                if Date().timeIntervalSince1970 - start.timeIntervalSince1970 > 20 {
                    throw Error.connection("The connection pool timed out")
                }
            }
            connection = connectionPool.removeFirst()
            activeConnections += 1
        }
        defer {
            Database.activeLock.locked {
                // Recycle connection
                connectionPool.append(connection!)
                activeConnections -= 1
            }
        }
        do {
            result = try connection!.execute(query, values)
        } catch {
            // Catch connection errors (e.g. timeout) and retry the request one time
            connection = try makeConnection()
            result = try connection!.execute(query, values)
        }
        return result
    }

        self.maxPoolSize = poolSize
        self.connectionPool = [Connection]()
        self.activeConnections = 0
        self.poolSemaphore = DispatchSemaphore(value: Int(poolSize))
    }
    
    private let host: String
