/**
   * Creates connection objects and pushes it into queue.
   *
   * @param factory Used to create JDBConnection implementations.
   * @param poolSize Number of JDBConnection implementations to create.
   * @param leaseTimeInMillis How long the client can use the connection before it expires.
   */
  public ConnectionPool(JdbConnectionFactory factory, int poolSize, long leaseTimeInMillis) {
    for (int i = 0; i < poolSize; i++) {
      pooled.addLast(factory.create());
    }

    this.factory = factory;
    this.leaseTimeInMillis = leaseTimeInMillis;
  }
  private JdbConnection createReplacementIfExpiredConnFound() throws ConnectionPoolException {
    // check for the first expired connection , close it and create a replacement
    // throw exception if replacement is not possible

    Entry<JdbConnection, Instant> entry =
        borrowed
            .entrySet()
            .stream()
            .filter(e -> hasExpired(e.getValue()))
            .findFirst()
            .orElseThrow(() -> new ConnectionPoolException("No connections available"));

    entry.getKey().close();
    borrowed.remove(entry.getKey());
    JdbConnection newJdbConnection = factory.create();
    borrowed.put(newJdbConnection, Instant.now());
    return newJdbConnection;
  }