Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import tech.ydb.jdbc.YdbTracer;
import tech.ydb.jdbc.exception.ExceptionFactory;
import tech.ydb.jdbc.exception.YdbConditionallyRetryableException;
import tech.ydb.jdbc.exception.YdbUnavailbaleException;
import tech.ydb.jdbc.query.YdbQuery;
import tech.ydb.query.QueryStream;
import tech.ydb.query.QueryTransaction;
Expand Down Expand Up @@ -128,7 +129,7 @@ protected void commitImpl(YdbContext ctx, YdbValidator validator, QueryTransacti
tracer.query(commitQuery);
return query.execute();
});
} catch (YdbConditionallyRetryableException ex) {
} catch (YdbConditionallyRetryableException | YdbUnavailbaleException ex) {
Result<DataQueryResult> res = validateRetryCtx.supplyResult(
session -> session.executeDataQuery(validateQuery, TxControl.snapshotRo(), params)
).join();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,17 @@ public static SQLException createException(String message, UnexpectedResultExcep
}

// transport problems are translated to SQLTransientConnectionException
if (code == StatusCode.TRANSPORT_UNAVAILABLE || code == StatusCode.UNAVAILABLE) {
if (code == StatusCode.TRANSPORT_UNAVAILABLE) {
return new YdbUnavailbaleException(message, sqlState, vendorCode, cause);
}

// timeouts are translated to SQLTimeoutException
if (code == StatusCode.TIMEOUT ||
code == StatusCode.CLIENT_DEADLINE_EXPIRED ||
code == StatusCode.CLIENT_DEADLINE_EXCEEDED) {
if (code == StatusCode.CLIENT_DEADLINE_EXPIRED || code == StatusCode.CLIENT_DEADLINE_EXCEEDED) {
return new YdbTimeoutException(message, sqlState, vendorCode, cause);
}

// all others transient problems are translated to base SQLTransientException
if (code.isRetryable(true)) {
if (code.isRetryable(true) || code == StatusCode.TIMEOUT) {
return new YdbConditionallyRetryableException(message, sqlState, vendorCode, cause);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import tech.ydb.jdbc.YdbConnection;
import tech.ydb.jdbc.exception.YdbConditionallyRetryableException;
import tech.ydb.jdbc.exception.YdbRetryableException;
import tech.ydb.jdbc.exception.YdbTimeoutException;
import tech.ydb.jdbc.impl.YdbTracerImpl;
import tech.ydb.jdbc.impl.helper.ExceptionAssert;
import tech.ydb.jdbc.impl.helper.JdbcConnectionExtention;
Expand Down Expand Up @@ -155,6 +156,34 @@ public void commitedTxTest() throws SQLException {
}
}

@Test
public void unavailableTxTest() throws SQLException {
String url = jdbcURL.withArg("withTxValidationTable", "tx1_store").build();
try (Connection conn = DriverManager.getConnection(url)) {
ErrorTxTracer tracer = YdbTracerImpl.use(new ErrorTxTracer());
// table was created automatically
assertTxCount("tx1_store", 0);

conn.setAutoCommit(false);

conn.createStatement().execute("DELETE FROM tx1_store");
// throw condintionally retryable exception AFTER commit
tracer.throwErrorOn("<-- Status", Status.of(StatusCode.TRANSPORT_UNAVAILABLE));
conn.commit(); // no error, tx is validated successfully

assertTxCount("tx1_store", 1);

conn.createStatement().execute("DELETE FROM tx1_store");
// throw condintionally retryable exception BEFORE commit
tracer.throwErrorOn("--> commit-and-store-tx", Status.of(StatusCode.TRANSPORT_UNAVAILABLE));
ExceptionAssert.sqlRecoverable("Transaction wasn't committed", conn::commit);

Assert.assertNull(tracer.error);
} finally {
jdbc.connection().createStatement().execute("DROP TABLE tx1_store");
}
}

@Test
public void executeDataQueryTest() throws SQLException {
String url = jdbcURL.withArg("withTxValidationTable", "tx1_store").build();
Expand All @@ -176,6 +205,11 @@ public void executeDataQueryTest() throws SQLException {
YdbRetryableException e2 = Assertions.assertThrows(YdbRetryableException.class,
() -> st.execute("DELETE FROM tx1_store"));
Assertions.assertEquals(Status.of(StatusCode.ABORTED), e2.getStatus());

tracer.throwErrorOn("<-- Status", Status.of(StatusCode.CLIENT_DEADLINE_EXCEEDED));
YdbTimeoutException e3 = Assertions.assertThrows(YdbTimeoutException.class,
() -> st.execute("DELETE FROM tx1_store"));
Assertions.assertEquals(Status.of(StatusCode.CLIENT_DEADLINE_EXCEEDED), e3.getStatus());
}


Expand Down