Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction timeout support for regular JDBC transactions #3238

Open
lightbody opened this issue Nov 19, 2024 · 0 comments
Open

Transaction timeout support for regular JDBC transactions #3238

lightbody opened this issue Nov 19, 2024 · 0 comments

Comments

@lightbody
Copy link
Contributor

Feature description

The Micronaut Data Transaction manager has code that wires up timeout attributes on the @TransactionalAdvice / @Transactional annotations up through the transaction definition, but then it doesn't do anything if you're using the basic JDBC transaction manager. It does seem to plumb through for Hibernate, Mongo, and Spring, but not the vanilla JDBC one.

My workaround on 3.x is to proxy the DataSource like so:

public class TimeoutAwareDataSource implements DataSource {
    private final DataSource delegate;

    public TimeoutAwareDataSource(DataSource delegate) {
        this.delegate = delegate;
    }

    @Override
    public Connection getConnection() throws SQLException {
        final Connection connection = delegate.getConnection();
        return new TimeoutAwareConnection(connection, this);
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        final Connection connection = delegate.getConnection(username, password);
        return new TimeoutAwareConnection(connection, this);
    }

    // a bunch of other proxied methods
}
import io.micronaut.transaction.jdbc.DataSourceUtils;
//snip

public class TimeoutAwareConnection implements Connection {
    private final Connection inner;
    private final DataSource dataSource;

    public TimeoutAwareConnection(Connection inner, DataSource dataSource) {
        this.inner = inner;
        this.dataSource = dataSource;
    }

    @Override
    public Statement createStatement() throws SQLException {
        final Statement statement = inner.createStatement();
        DataSourceUtils.applyTransactionTimeout(statement, dataSource);
        return statement;
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        final PreparedStatement preparedStatement = inner.prepareStatement(sql);
        DataSourceUtils.applyTransactionTimeout(preparedStatement, dataSource);
        return preparedStatement;
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        final CallableStatement callableStatement = inner.prepareCall(sql);
        DataSourceUtils.applyTransactionTimeout(callableStatement, dataSource);
        return callableStatement;
    }

    // a bunch of other proxied methods
}

By doing this, we are seeing timeouts actually work on the 3.x line. We plan to upgrade to 4.x soon and this will have to change because DataSourceUtils doesn't even exist in that code, but it'll be the same approach until this capability is natively introduced.

I might also suggest a bit of docs on timeouts, since it's not really covered today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant