-
Notifications
You must be signed in to change notification settings - Fork 143
IGNITE-27947 Fix rollback for client piggyback tx #7844
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
base: main
Are you sure you want to change the base?
Changes from 5 commits
4e91edf
74b3741
e7df787
46e0cd1
49c0fc2
cdf9608
f649f76
6c2bf2f
52b8fe9
dfa9bed
0264715
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -95,6 +95,7 @@ | |
| import org.apache.ignite.client.handler.requests.table.ClientSchemasGetRequest; | ||
| import org.apache.ignite.client.handler.requests.table.ClientStreamerBatchSendRequest; | ||
| import org.apache.ignite.client.handler.requests.table.ClientStreamerWithReceiverBatchSendRequest; | ||
| import org.apache.ignite.client.handler.requests.table.ClientTableCommon; | ||
| import org.apache.ignite.client.handler.requests.table.ClientTableGetQualifiedRequest; | ||
| import org.apache.ignite.client.handler.requests.table.ClientTableGetRequest; | ||
| import org.apache.ignite.client.handler.requests.table.ClientTablePartitionPrimaryReplicasGetRequest; | ||
|
|
@@ -189,6 +190,7 @@ | |
| import org.apache.ignite.security.exception.InvalidCredentialsException; | ||
| import org.apache.ignite.security.exception.UnsupportedAuthenticationTypeException; | ||
| import org.apache.ignite.sql.SqlBatchException; | ||
| import org.apache.ignite.table.IgniteTables; | ||
| import org.apache.ignite.tx.RetriableTransactionException; | ||
| import org.jetbrains.annotations.Nullable; | ||
| import org.jetbrains.annotations.TestOnly; | ||
|
|
@@ -291,6 +293,25 @@ public class ClientInboundMessageHandler | |
|
|
||
| private final HandshakeEventLoopSwitcher handshakeEventLoopSwitcher; | ||
|
|
||
| /** | ||
| * Tracks mappings between the first {@code requestId} and the {@code resourceId} | ||
| * holding the Tx object for directly mapped transactions. The process is not localized. | ||
| * | ||
| * <p><b>Mappings are created:</b> | ||
| * <ul> | ||
| * <li>When a direct transaction is created in {@link ClientTableCommon#readTx(ClientMessageUnpacker, HybridTimestampTracker, | ||
| * ClientResourceRegistry, TxManager, IgniteTables, NotificationSender, long[], long, Map)}. | ||
| * </li> | ||
| * </ul> | ||
| * | ||
| * <p><b>Mappings are removed:</b> | ||
| * <ul> | ||
| * <li>During a rollback request.</li> | ||
| * <li>After the first request response is sent to the client.</li> | ||
| * </ul> | ||
| */ | ||
| private final Map<Long, Long> firstReqToTxResMap = new ConcurrentHashMap<>(); | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
|
|
@@ -899,70 +920,72 @@ private CompletableFuture<ResponseWriter> processOperation( | |
| return ClientTableGetRequest.process(in, igniteTables); | ||
|
|
||
| case ClientOp.TUPLE_UPSERT: | ||
| return ClientTupleUpsertRequest.process( | ||
| in, igniteTables, resources, txManager, clockService, notificationSender(requestId), tsTracker); | ||
| return ClientTupleUpsertRequest.process(in, igniteTables, resources, txManager, clockService, notificationSender(requestId), | ||
| tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_GET: | ||
| return ClientTupleGetRequest.process(in, igniteTables, resources, txManager, clockService, tsTracker); | ||
| return ClientTupleGetRequest.process(in, igniteTables, resources, txManager, clockService, tsTracker, requestId, | ||
| firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_UPSERT_ALL: | ||
| return ClientTupleUpsertAllRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_GET_ALL: | ||
| return ClientTupleGetAllRequest.process(in, igniteTables, resources, txManager, clockService, tsTracker, | ||
| clientContext.hasFeature(TX_CLIENT_GETALL_SUPPORTS_TX_OPTIONS)); | ||
| requestId, firstReqToTxResMap, clientContext.hasFeature(TX_CLIENT_GETALL_SUPPORTS_TX_OPTIONS)); | ||
|
|
||
| case ClientOp.TUPLE_GET_AND_UPSERT: | ||
| return ClientTupleGetAndUpsertRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_INSERT: | ||
| return ClientTupleInsertRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_INSERT_ALL: | ||
| return ClientTupleInsertAllRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_REPLACE: | ||
| return ClientTupleReplaceRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_REPLACE_EXACT: | ||
| return ClientTupleReplaceExactRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_GET_AND_REPLACE: | ||
| return ClientTupleGetAndReplaceRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_DELETE: | ||
| return ClientTupleDeleteRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_DELETE_ALL: | ||
| return ClientTupleDeleteAllRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_DELETE_EXACT: | ||
| return ClientTupleDeleteExactRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_DELETE_ALL_EXACT: | ||
| return ClientTupleDeleteAllExactRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_GET_AND_DELETE: | ||
| return ClientTupleGetAndDeleteRequest.process(in, igniteTables, resources, txManager, clockService, | ||
| notificationSender(requestId), tsTracker); | ||
| notificationSender(requestId), tsTracker, requestId, firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_CONTAINS_KEY: | ||
| return ClientTupleContainsKeyRequest.process(in, igniteTables, resources, txManager, clockService, tsTracker); | ||
| return ClientTupleContainsKeyRequest.process(in, igniteTables, resources, txManager, clockService, tsTracker, requestId, | ||
| firstReqToTxResMap); | ||
|
|
||
| case ClientOp.TUPLE_CONTAINS_ALL_KEYS: | ||
| return ClientTupleContainsAllKeysRequest.process(in, igniteTables, resources, txManager, clockService, tsTracker, | ||
| clientContext.hasFeature(TX_CLIENT_GETALL_SUPPORTS_TX_OPTIONS)); | ||
| requestId, firstReqToTxResMap, clientContext.hasFeature(TX_CLIENT_GETALL_SUPPORTS_TX_OPTIONS)); | ||
|
|
||
| case ClientOp.JDBC_CONNECT: | ||
| return ClientJdbcConnectRequest.execute(in, jdbcQueryEventHandler, resolveCurrentUsername()); | ||
|
|
@@ -1011,7 +1034,7 @@ private CompletableFuture<ResponseWriter> processOperation( | |
| clientContext.hasFeature(TX_PIGGYBACK), clientContext.hasFeature(TX_DIRECT_MAPPING_SEND_REMOTE_WRITES), tsTracker); | ||
|
|
||
| case ClientOp.TX_ROLLBACK: | ||
| return ClientTransactionRollbackRequest.process(in, resources, metrics, igniteTables, | ||
| return ClientTransactionRollbackRequest.process(in, resources, metrics, igniteTables, firstReqToTxResMap, | ||
| clientContext.hasFeature(TX_PIGGYBACK), clientContext.hasFeature(TX_DIRECT_MAPPING_SEND_REMOTE_WRITES)); | ||
|
|
||
| case ClientOp.COMPUTE_EXECUTE: | ||
|
|
@@ -1066,6 +1089,7 @@ private CompletableFuture<ResponseWriter> processOperation( | |
| igniteTables, | ||
| clockService, | ||
| notificationSender(requestId), | ||
| firstReqToTxResMap, | ||
| resolveCurrentUsername(), | ||
| clientContext.hasFeature(SQL_MULTISTATEMENT_SUPPORT), | ||
| clientContext.hasFeature(SQL_PARTITION_AWARENESS_TABLE_NAME), | ||
|
|
@@ -1097,12 +1121,12 @@ partitionOperationsExecutor, in, queryProcessor, requestId, cancelHandles, tsTra | |
|
|
||
| case ClientOp.SQL_QUERY_META: | ||
| return ClientSqlQueryMetadataRequest.process( | ||
| partitionOperationsExecutor, in, queryProcessor, resources, tsTracker | ||
| partitionOperationsExecutor, in, queryProcessor, resources, tsTracker, requestId, firstReqToTxResMap | ||
| ); | ||
|
|
||
| case ClientOp.SQL_EXEC_BATCH: | ||
| return ClientSqlExecuteBatchRequest.process( | ||
| in, queryProcessor, resources, requestId, cancelHandles, tsTracker, | ||
| in, queryProcessor, resources, requestId, cancelHandles, tsTracker, firstReqToTxResMap, | ||
| resolveCurrentUsername() | ||
| ); | ||
|
|
||
|
|
@@ -1171,6 +1195,7 @@ private void processOperationInternal( | |
| if (err != null) { | ||
| writeError(requestId, opCode, (Throwable) err, ctx, false); | ||
| metrics.requestsFailedIncrement(); | ||
| firstReqToTxResMap.remove(requestId); | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -1200,6 +1225,8 @@ private void processOperationInternal( | |
| writeError(requestId, opCode, e, ctx, false); | ||
| metrics.requestsFailedIncrement(); | ||
| } | ||
|
|
||
| firstReqToTxResMap.remove(requestId); | ||
|
||
| }); | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.