Skip to content

OracleReactiveJdbcAdaptor.publishConnection should timeout if Oracle JDBC connection publisher does not resolve #136

Closed
@volcanic-tephra

Description

@volcanic-tephra

When creating a connection using the r2dbc ConnectionFactoryOptions the Oracle adaptor will use ForkJoinPool.commonPool() as the executor.

Note: I raised this then noticed PR #131. However the suggestion below would be complimentary and make the solution more robust (both a default fallback and an eventual exception if it still fails).

If the executor has no free threads then the request to create a connection will hang indefinitely. The publishConnection Publisher should timeout and throw an exception as there is currently zero information that this is the cause of the failure.

The timeout default could be reasonably long, there just needs to be some feedback to troubleshoot.


  public Publisher<? extends Connection> publishConnection(
    DataSource dataSource, Executor executor) {

    long timeout = 10000; // Get from configuration
    OracleDataSource oracleDataSource = unwrapOracleDataSource(dataSource);
    return Mono.from(adaptFlowPublisher(() ->
        oracleDataSource
          .createConnectionBuilder()
          .executorOracle(executor)
          .buildConnectionPublisherOracle()))
      .timeout(Duration.ofMillis(timeout)) // PREVENT THIS FROM HANGING FOREVER!!!
      .onErrorMap(R2dbcException.class, error ->
        error.getErrorCode() == 18714 // ORA-18714 : Login timeout expired
          ? new R2dbcTimeoutException(error.getMessage(),
              error.getSqlState(), error.getErrorCode(), error.getCause())
          : error);
  }

The work around is to create a custom Executor and supply this to the Connection factory.

var executor = Executors.newFixedThreadPool(threads);

var factory = ConnectionFactories.get(
        ConnectionFactoryOptions.builder()
          .option(OracleR2dbcOptions.EXECUTOR, executor)
          .option(ConnectionFactoryOptions.DRIVER, "pool")
          .option(ConnectionFactoryOptions.PROTOCOL, "oracle")
          .option(ConnectionFactoryOptions.HOST, properties.getHost())
          .option(ConnectionFactoryOptions.PORT, properties.getPort())
          .option(ConnectionFactoryOptions.DATABASE, properties.getDatabase())
          .option(ConnectionFactoryOptions.USER, properties.getUser())          
          .option(ConnectionFactoryOptions.PASSWORD, properties.getPassword())
          .build());

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions