Search in sources :

Example 1 with TransactionOptions

use of com.mongodb.TransactionOptions in project mongo-java-driver by mongodb.

the class AbstractUnifiedTest method executeOperations.

private void executeOperations(final BsonArray operations, final boolean throwExceptions) {
    FailPoint failPoint = null;
    ServerAddress currentPrimary = null;
    try {
        for (BsonValue cur : operations) {
            final BsonDocument operation = cur.asDocument();
            String operationName = operation.getString("name").getValue();
            BsonValue expectedResult = operation.get("result");
            String receiver = operation.getString("object").getValue();
            ClientSession clientSession = receiver.startsWith("session") ? sessionsMap.get(receiver) : null;
            if (clientSession == null) {
                clientSession = operation.getDocument("arguments", new BsonDocument()).containsKey("session") ? sessionsMap.get(operation.getDocument("arguments").getString("session").getValue()) : null;
            }
            try {
                if (operationName.equals("startTransaction")) {
                    BsonDocument arguments = operation.getDocument("arguments", new BsonDocument());
                    if (arguments.containsKey("options")) {
                        TransactionOptions transactionOptions = createTransactionOptions(arguments.getDocument("options"));
                        nonNullClientSession(clientSession).startTransaction(transactionOptions);
                    } else {
                        nonNullClientSession(clientSession).startTransaction();
                    }
                } else if (operationName.equals("commitTransaction")) {
                    nonNullClientSession(clientSession).commitTransaction();
                } else if (operationName.equals("abortTransaction")) {
                    nonNullClientSession(clientSession).abortTransaction();
                } else if (operationName.equals("withTransaction")) {
                    final BsonDocument arguments = operation.getDocument("arguments", new BsonDocument());
                    TransactionOptions transactionOptions = null;
                    if (arguments.containsKey("options")) {
                        transactionOptions = createTransactionOptions(arguments.getDocument("options"));
                    }
                    if (transactionOptions == null) {
                        nonNullClientSession(clientSession).withTransaction(new TransactionBody<Object>() {

                            @Override
                            public Void execute() {
                                executeOperations(arguments.getDocument("callback").getArray("operations"), true);
                                return null;
                            }
                        });
                    } else {
                        nonNullClientSession(clientSession).withTransaction(new TransactionBody<Object>() {

                            @Override
                            public Void execute() {
                                executeOperations(arguments.getDocument("callback").getArray("operations"), true);
                                return null;
                            }
                        }, transactionOptions);
                    }
                } else if (operationName.equals("targetedFailPoint")) {
                    assertNull(failPoint);
                    failPoint = new TargetedFailPoint(operation);
                    failPoint.executeFailPoint();
                } else if (operationName.equals("configureFailPoint")) {
                    assertNull(failPoint);
                    failPoint = new FailPoint(operation);
                    failPoint.executeFailPoint();
                } else if (operationName.equals("startThread")) {
                    String target = operation.getDocument("arguments").getString("name").getValue();
                    executorServiceMap.put(target, Executors.newSingleThreadExecutor());
                } else if (operationName.equals("runOnThread")) {
                    String target = operation.getDocument("arguments").getString("name").getValue();
                    ExecutorService executorService = executorServiceMap.get(target);
                    Callable<Exception> callable = createCallable(operation.getDocument("arguments").getDocument("operation"));
                    futureMap.put(target, executorService.submit(callable));
                } else if (operationName.equals("wait")) {
                    Thread.sleep(operation.getDocument("arguments").getNumber("ms").longValue());
                } else if (operationName.equals("waitForThread")) {
                    String target = operation.getDocument("arguments").getString("name").getValue();
                    Exception exceptionFromFuture = futureMap.remove(target).get(5, SECONDS);
                    if (exceptionFromFuture != null) {
                        throw exceptionFromFuture;
                    }
                } else if (operationName.equals("waitForEvent")) {
                    String event = operation.getDocument("arguments").getString("event").getValue();
                    int count = operation.getDocument("arguments").getNumber("count").intValue();
                    long timeoutMillis = TimeUnit.SECONDS.toMillis(5);
                    switch(event) {
                        case "PoolClearedEvent":
                            connectionPoolListener.waitForEvent(ConnectionPoolClearedEvent.class, count, timeoutMillis, MILLISECONDS);
                            break;
                        case "PoolReadyEvent":
                            connectionPoolListener.waitForEvent(ConnectionPoolReadyEvent.class, count, timeoutMillis, MILLISECONDS);
                            break;
                        case "ServerMarkedUnknownEvent":
                            serverListener.waitForEvent(ServerType.UNKNOWN, count, timeoutMillis, MILLISECONDS);
                            break;
                        default:
                            throw new UnsupportedOperationException("Unsupported event type: " + event);
                    }
                } else if (operationName.equals("assertEventCount")) {
                    String event = operation.getDocument("arguments").getString("event").getValue();
                    int expectedCount = operation.getDocument("arguments").getNumber("count").intValue();
                    int actualCount = -1;
                    switch(event) {
                        case "PoolClearedEvent":
                            actualCount = connectionPoolListener.countEvents(ConnectionPoolClearedEvent.class);
                            break;
                        case "PoolReadyEvent":
                            actualCount = connectionPoolListener.countEvents(ConnectionPoolReadyEvent.class);
                            break;
                        case "ServerMarkedUnknownEvent":
                            actualCount = serverListener.countEvents(ServerType.UNKNOWN);
                            break;
                        default:
                            throw new UnsupportedOperationException("Unsupported event type: " + event);
                    }
                    assertEquals(event + " counts not equal", expectedCount, actualCount);
                } else if (operationName.equals("recordPrimary")) {
                    currentPrimary = getCurrentPrimary();
                } else if (operationName.equals("waitForPrimaryChange")) {
                    long startTimeMillis = System.currentTimeMillis();
                    int timeoutMillis = operation.getDocument("arguments").getNumber("timeoutMS").intValue();
                    ServerAddress newPrimary = getCurrentPrimary();
                    while (newPrimary == null || newPrimary.equals(currentPrimary)) {
                        if (startTimeMillis + timeoutMillis <= System.currentTimeMillis()) {
                            fail("Timed out waiting for primary change");
                        }
                        // noinspection BusyWait
                        Thread.sleep(50);
                        newPrimary = getCurrentPrimary();
                    }
                } else if (operationName.equals("runAdminCommand")) {
                    collectionHelper.runAdminCommand(operation.getDocument("arguments").getDocument("command"));
                } else if (operationName.equals("assertSessionPinned")) {
                    final BsonDocument arguments = operation.getDocument("arguments", new BsonDocument());
                    assertNotNull(sessionsMap.get(arguments.getString("session").getValue()).getPinnedServerAddress());
                } else if (operationName.equals("assertSessionUnpinned")) {
                    final BsonDocument arguments = operation.getDocument("arguments", new BsonDocument());
                    assertNull(sessionsMap.get(arguments.getString("session").getValue()).getPinnedServerAddress());
                } else if (operationName.equals("assertSessionTransactionState")) {
                    final BsonDocument arguments = operation.getDocument("arguments", new BsonDocument());
                    ClientSession session = sessionsMap.get(arguments.getString("session").getValue());
                    String state = arguments.getString("state").getValue();
                    if (state.equals("starting") || state.equals("in_progress")) {
                        assertTrue(session.hasActiveTransaction());
                    } else {
                        assertFalse(session.hasActiveTransaction());
                    }
                } else if (operationName.equals("endSession")) {
                    clientSession.close();
                } else if (operation.getBoolean("error", BsonBoolean.FALSE).getValue()) {
                    try {
                        helper.getOperationResults(operation, clientSession);
                        fail("Error expected but none thrown");
                    } catch (Exception e) {
                    // Expected failure ignore
                    }
                } else if (operationName.equals("assertDifferentLsidOnLastTwoCommands")) {
                    List<CommandEvent> events = lastTwoCommandEvents();
                    String eventsJson = commandListener.getCommandStartedEvents().stream().map(e -> ((CommandStartedEvent) e).getCommand().toJson()).collect(Collectors.joining(", "));
                    assertNotEquals(eventsJson, ((CommandStartedEvent) events.get(0)).getCommand().getDocument("lsid"), ((CommandStartedEvent) events.get(1)).getCommand().getDocument("lsid"));
                } else if (operationName.equals("assertSameLsidOnLastTwoCommands")) {
                    List<CommandEvent> events = lastTwoCommandEvents();
                    String eventsJson = commandListener.getCommandStartedEvents().stream().map(e -> ((CommandStartedEvent) e).getCommand().toJson()).collect(Collectors.joining(", "));
                    assertEquals(eventsJson, ((CommandStartedEvent) events.get(0)).getCommand().getDocument("lsid"), ((CommandStartedEvent) events.get(1)).getCommand().getDocument("lsid"));
                } else if (operationName.equals("assertSessionDirty")) {
                    assertNotNull(clientSession);
                    assertNotNull(clientSession.getServerSession());
                    assertTrue(clientSession.getServerSession().isMarkedDirty());
                } else if (operationName.equals("assertSessionNotDirty")) {
                    assertNotNull(clientSession);
                    assertNotNull(clientSession.getServerSession());
                    assertFalse(clientSession.getServerSession().isMarkedDirty());
                } else if (operationName.equals("assertCollectionExists")) {
                    assertCollectionExists(operation, true);
                } else if (operationName.equals("assertCollectionNotExists")) {
                    assertCollectionExists(operation, false);
                } else if (operationName.equals("assertIndexExists")) {
                    assertIndexExists(operation, true);
                } else if (operationName.equals("assertIndexNotExists")) {
                    assertIndexExists(operation, false);
                } else {
                    BsonDocument actualOutcome = helper.getOperationResults(operation, clientSession);
                    if (expectedResult != null) {
                        BsonValue actualResult = actualOutcome.get("result");
                        if (actualResult.isDocument()) {
                            if (((BsonDocument) actualResult).containsKey("recoveryToken")) {
                                ((BsonDocument) actualResult).remove("recoveryToken");
                            }
                        }
                        assertEquals("Expected operation result differs from actual", expectedResult, actualResult);
                    }
                }
                assertFalse(String.format("Expected error '%s' but none thrown for operation %s", getErrorContainsField(expectedResult), operationName), hasErrorContainsField(expectedResult));
                assertFalse(String.format("Expected error code '%s' but none thrown for operation %s", getErrorCodeNameField(expectedResult), operationName), hasErrorCodeNameField(expectedResult));
            } catch (RuntimeException e) {
                if (!assertExceptionState(e, expectedResult, operationName) || throwExceptions) {
                    throw e;
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    } finally {
        if (failPoint != null) {
            failPoint.disableFailPoint();
        }
    }
}
Also used : Document(org.bson.Document) ServerDescription(com.mongodb.connection.ServerDescription) ClusterFixture.getConnectionString(com.mongodb.ClusterFixture.getConnectionString) BsonValue(org.bson.BsonValue) Collections.singletonList(java.util.Collections.singletonList) MongoWriteConcernException(com.mongodb.MongoWriteConcernException) StreamFactoryFactory(com.mongodb.connection.StreamFactoryFactory) Future(java.util.concurrent.Future) ClusterFixture.isSharded(com.mongodb.ClusterFixture.isSharded) Fixture.getMongoClientSettingsBuilder(com.mongodb.client.Fixture.getMongoClientSettingsBuilder) SocketSettings(com.mongodb.connection.SocketSettings) BsonArray(org.bson.BsonArray) After(org.junit.After) Map(java.util.Map) ServerType(com.mongodb.connection.ServerType) ClusterFixture.getMultiMongosConnectionString(com.mongodb.ClusterFixture.getMultiMongosConnectionString) Assert.fail(org.junit.Assert.fail) ReadConcern(com.mongodb.ReadConcern) Parameterized(org.junit.runners.Parameterized) CommandMonitoringTestHelper.assertEventsEquality(com.mongodb.client.CommandMonitoringTestHelper.assertEventsEquality) CommandEvent(com.mongodb.event.CommandEvent) CollectionHelper(com.mongodb.client.test.CollectionHelper) MongoException(com.mongodb.MongoException) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) ConnectionPoolClearedEvent(com.mongodb.event.ConnectionPoolClearedEvent) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) List(java.util.List) Block(com.mongodb.Block) Assert.assertFalse(org.junit.Assert.assertFalse) TestConnectionPoolListener(com.mongodb.internal.connection.TestConnectionPoolListener) Assume.assumeTrue(org.junit.Assume.assumeTrue) MongoClientSettings(com.mongodb.MongoClientSettings) ReadPreference(com.mongodb.ReadPreference) CommandMonitoringTestHelper.getExpectedEvents(com.mongodb.client.CommandMonitoringTestHelper.getExpectedEvents) BsonBoolean(org.bson.BsonBoolean) Assume.assumeFalse(org.junit.Assume.assumeFalse) MongoCommandException(com.mongodb.MongoCommandException) ClusterSettings(com.mongodb.connection.ClusterSettings) RunWith(org.junit.runner.RunWith) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) BsonString(org.bson.BsonString) ServerSettings(com.mongodb.connection.ServerSettings) BsonDocument(org.bson.BsonDocument) ArrayList(java.util.ArrayList) TransactionOptions(com.mongodb.TransactionOptions) TestCommandListener(com.mongodb.internal.connection.TestCommandListener) CreateCollectionOptions(com.mongodb.client.model.CreateCollectionOptions) DocumentCodec(org.bson.codecs.DocumentCodec) Fixture.getMongoClient(com.mongodb.client.Fixture.getMongoClient) Math.toIntExact(java.lang.Math.toIntExact) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) ServerAddress(com.mongodb.ServerAddress) ClusterFixture.setDirectConnection(com.mongodb.ClusterFixture.setDirectConnection) MongoNamespace(com.mongodb.MongoNamespace) Assert.assertNotNull(org.junit.Assert.assertNotNull) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) BsonDocumentCodec(org.bson.codecs.BsonDocumentCodec) ClusterFixture.isDataLakeTest(com.mongodb.ClusterFixture.isDataLakeTest) Assert.assertNotEquals(org.junit.Assert.assertNotEquals) TimeUnit(java.util.concurrent.TimeUnit) ConnectionPoolReadyEvent(com.mongodb.event.ConnectionPoolReadyEvent) ConnectionString(com.mongodb.ConnectionString) Assert.assertNull(org.junit.Assert.assertNull) ClientSessionOptions(com.mongodb.ClientSessionOptions) ReadConcernLevel(com.mongodb.ReadConcernLevel) ClusterFixture.serverVersionAtLeast(com.mongodb.ClusterFixture.serverVersionAtLeast) Nullable(com.mongodb.lang.Nullable) BsonInt32(org.bson.BsonInt32) WriteConcern(com.mongodb.WriteConcern) CommandStartedEvent(com.mongodb.event.CommandStartedEvent) SECONDS(java.util.concurrent.TimeUnit.SECONDS) Assert.assertEquals(org.junit.Assert.assertEquals) ServerAddress(com.mongodb.ServerAddress) ClusterFixture.getConnectionString(com.mongodb.ClusterFixture.getConnectionString) ClusterFixture.getMultiMongosConnectionString(com.mongodb.ClusterFixture.getMultiMongosConnectionString) BsonString(org.bson.BsonString) ConnectionString(com.mongodb.ConnectionString) Callable(java.util.concurrent.Callable) MongoWriteConcernException(com.mongodb.MongoWriteConcernException) MongoException(com.mongodb.MongoException) MongoCommandException(com.mongodb.MongoCommandException) BsonDocument(org.bson.BsonDocument) TransactionOptions(com.mongodb.TransactionOptions) CommandStartedEvent(com.mongodb.event.CommandStartedEvent) ExecutorService(java.util.concurrent.ExecutorService) CommandEvent(com.mongodb.event.CommandEvent) Collections.singletonList(java.util.Collections.singletonList) List(java.util.List) ArrayList(java.util.ArrayList) BsonValue(org.bson.BsonValue)

Example 2 with TransactionOptions

use of com.mongodb.TransactionOptions in project mongo-java-driver by mongodb.

the class TransactionExample method updateEmployeeInfoUsingWithTransactionHelper.

@Test
public void updateEmployeeInfoUsingWithTransactionHelper() {
    MongoCollection<Document> employeesCollection = client.getDatabase("hr").getCollection("employees");
    MongoCollection<Document> eventsCollection = client.getDatabase("reporting").getCollection("events");
    TransactionOptions txnOptions = TransactionOptions.builder().readPreference(ReadPreference.primary()).readConcern(ReadConcern.MAJORITY).writeConcern(WriteConcern.MAJORITY).build();
    try (ClientSession clientSession = client.startSession()) {
        clientSession.withTransaction(() -> {
            employeesCollection.updateOne(clientSession, Filters.eq("employee", 3), Updates.set("status", "Inactive"));
            eventsCollection.insertOne(clientSession, new Document("employee", 3).append("status", new Document("new", "Inactive").append("old", "Active")));
            return null;
        }, txnOptions);
    } catch (MongoException e) {
        System.out.println("Transaction aborted. Caught exception during transaction.");
        throw e;
    }
}
Also used : MongoException(com.mongodb.MongoException) TransactionOptions(com.mongodb.TransactionOptions) ClientSession(com.mongodb.client.ClientSession) Document(org.bson.Document) ClusterFixture.isServerlessTest(com.mongodb.ClusterFixture.isServerlessTest) Test(org.junit.Test) ClusterFixture.isDataLakeTest(com.mongodb.ClusterFixture.isDataLakeTest)

Example 3 with TransactionOptions

use of com.mongodb.TransactionOptions in project mongo-java-driver by mongodb.

the class TransactionExample method updateEmployeeInfo.

private void updateEmployeeInfo() {
    MongoCollection<Document> employeesCollection = client.getDatabase("hr").getCollection("employees");
    MongoCollection<Document> eventsCollection = client.getDatabase("reporting").getCollection("events");
    TransactionOptions txnOptions = TransactionOptions.builder().readPreference(ReadPreference.primary()).readConcern(ReadConcern.MAJORITY).writeConcern(WriteConcern.MAJORITY).build();
    try (ClientSession clientSession = client.startSession()) {
        clientSession.startTransaction(txnOptions);
        employeesCollection.updateOne(clientSession, Filters.eq("employee", 3), Updates.set("status", "Inactive"));
        eventsCollection.insertOne(clientSession, new Document("employee", 3).append("status", new Document("new", "Inactive").append("old", "Active")));
        commitWithRetry(clientSession);
    }
}
Also used : TransactionOptions(com.mongodb.TransactionOptions) ClientSession(com.mongodb.client.ClientSession) Document(org.bson.Document)

Aggregations

TransactionOptions (com.mongodb.TransactionOptions)3 Document (org.bson.Document)3 ClusterFixture.isDataLakeTest (com.mongodb.ClusterFixture.isDataLakeTest)2 MongoException (com.mongodb.MongoException)2 ClientSession (com.mongodb.client.ClientSession)2 Test (org.junit.Test)2 Block (com.mongodb.Block)1 ClientSessionOptions (com.mongodb.ClientSessionOptions)1 ClusterFixture.getConnectionString (com.mongodb.ClusterFixture.getConnectionString)1 ClusterFixture.getMultiMongosConnectionString (com.mongodb.ClusterFixture.getMultiMongosConnectionString)1 ClusterFixture.isServerlessTest (com.mongodb.ClusterFixture.isServerlessTest)1 ClusterFixture.isSharded (com.mongodb.ClusterFixture.isSharded)1 ClusterFixture.serverVersionAtLeast (com.mongodb.ClusterFixture.serverVersionAtLeast)1 ClusterFixture.setDirectConnection (com.mongodb.ClusterFixture.setDirectConnection)1 ConnectionString (com.mongodb.ConnectionString)1 MongoClientSettings (com.mongodb.MongoClientSettings)1 MongoCommandException (com.mongodb.MongoCommandException)1 MongoNamespace (com.mongodb.MongoNamespace)1 MongoWriteConcernException (com.mongodb.MongoWriteConcernException)1 ReadConcern (com.mongodb.ReadConcern)1