public Connection getVerifiedConnection()

in wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsHelper.java [61:165]


  public Connection getVerifiedConnection(
      final boolean isInitialConnection,
      final HostListProviderService hostListProviderService,
      final String driverProtocol,
      final HostSpec hostSpec,
      final Properties props,
      final JdbcCallable<Connection, SQLException> connectFunc) throws SQLException {

    if (!this.rdsUtils.isWriterClusterDns(hostSpec.getHost())) {
      return connectFunc.call();
    }

    final Connection conn = connectFunc.call();

    String clusterInetAddress = null;
    try {
      clusterInetAddress = InetAddress.getByName(hostSpec.getHost()).getHostAddress();
    } catch (UnknownHostException e) {
      // ignore
    }

    final String hostInetAddress = clusterInetAddress;
    LOGGER.finest(() -> Messages.get("AuroraStaleDnsHelper.clusterEndpointDns",
        new Object[]{hostInetAddress}));

    if (clusterInetAddress == null) {
      return conn;
    }

    if (this.pluginService.getHostRole(conn) == HostRole.READER) {
      // This is if-statement is only reached if the connection url is a writer cluster endpoint.
      // If the new connection resolves to a reader instance, this means the topology is outdated.
      // Force refresh to update the topology.
      this.pluginService.forceRefreshHostList(conn);
    } else {
      this.pluginService.refreshHostList(conn);
    }

    LOGGER.finest(() -> Utils.logTopology(this.pluginService.getAllHosts()));

    if (this.writerHostSpec == null) {
      final HostSpec writerCandidate = this.getWriter();
      if (writerCandidate != null && this.rdsUtils.isRdsClusterDns(writerCandidate.getHost())) {
        return null;
      }
      this.writerHostSpec = writerCandidate;
    }

    LOGGER.finest(() -> Messages.get("AuroraStaleDnsHelper.writerHostSpec",
        new Object[]{this.writerHostSpec}));

    if (this.writerHostSpec == null) {
      return conn;
    }

    if (this.writerHostAddress == null) {
      try {
        this.writerHostAddress = InetAddress.getByName(this.writerHostSpec.getHost()).getHostAddress();
      } catch (UnknownHostException e) {
        // ignore
      }
    }

    LOGGER.finest(() -> Messages.get("AuroraStaleDnsHelper.writerInetAddress",
        new Object[]{this.writerHostAddress}));

    if (this.writerHostAddress == null) {
      return conn;
    }

    if (!writerHostAddress.equals(clusterInetAddress)) {
      // DNS resolves a cluster endpoint to a wrong writer
      // opens a connection to a proper writer node

      LOGGER.fine(() -> Messages.get("AuroraStaleDnsHelper.staleDnsDetected",
          new Object[]{this.writerHostSpec}));
      staleDNSDetectedCounter.inc();

      final List<HostSpec> allowedHosts = this.pluginService.getHosts();
      if (!Utils.containsUrl(allowedHosts, this.writerHostSpec.getUrl())) {
        throw new SQLException(
            Messages.get("AuroraStaleDnsHelper.currentWriterNotAllowed",
                new Object[] {
                    this.writerHostSpec == null ? "<null>" : this.writerHostSpec.getUrl(),
                    Utils.logTopology(allowedHosts, "")})
        );
      }

      final Connection writerConn = this.pluginService.connect(this.writerHostSpec, props);
      if (isInitialConnection) {
        hostListProviderService.setInitialConnectionHostSpec(this.writerHostSpec);
      }

      if (conn != null) {
        try {
          conn.close();
        } catch (final SQLException ex) {
          // ignore
        }
        return writerConn;
      }
    }

    return conn;
  }