eventuate-foundation / eventuate-common

Other
12 stars 20 forks source link

Reactive transactions are failing #91

Open dartartem opened 3 years ago

dartartem commented 3 years ago

When trying to use transactional operator:

@Autowired
protected TransactionalOperator transactionalOperator;
...
<db-mono>.as(transactionalOperator::transactional)

The following error appears:

Transaction is already completed - do not call commit or rollback more than once per transaction
org.springframework.transaction.IllegalTransactionStateException: Transaction is already completed - do not call commit or rollback more than once per transaction

Full Error Log

Originally, error appeared in eventuate-tram-core test:

  @Test
  public void shouldDoSomething() throws InterruptedException {
    String destination = "Destination-" + System.currentTimeMillis();
    String subscriberId = "SubscriberId-" + System.currentTimeMillis();

    CountDownLatch latch = new CountDownLatch(1);

    MessageHandler handler = message -> {
      logger.info("Got message=" + message);
      latch.countDown();
    };

    messageConsumer.subscribe(subscriberId, Collections.singleton(destination), handler);

    messageProducer
            .send(destination, MessageBuilder.withPayload("\"Hello\"").build())
            .as(transactionalOperator::transactional)
            .block(Duration.ofSeconds(30));

    assertTrue(String.format("Expected message. Subscriber %s for destination %s: ", subscriberId, destination), latch.await(60, TimeUnit.SECONDS));
  }

Reason is that eventuate-common declares TransactionAwareConnectionFactoryProxy and creates DatabaseClient using it:

https://github.com/eventuate-foundation/eventuate-common/blob/6189c65a26121096d11fb20df01fd99868fdbe7f/eventuate-common-spring-reactive-jdbc/src/main/java/io/eventuate/common/spring/jdbc/reactive/EventuateCommonReactiveDatabaseConfiguration.java#L29-L33

TransactionAwareConnectionFactoryProxy already wraps queries in transactions.

To have control over transactions is necessary to remove TransactionAwareConnectionFactoryProxy from the chain.

Problem was not handled by eventuate common tests because they hide exceptions here:

https://github.com/eventuate-foundation/eventuate-common/blob/6189c65a26121096d11fb20df01fd99868fdbe7f/eventuate-common-spring-reactive-jdbc/src/test/java/io/eventuate/common/spring/jdbc/reactive/EventuateCommonReactiveJdbcOperationsTest.java#L74-L84

Yes, you said that is not wise, and I also know it, but I really was thinking that I removed that code. My bad. I will be checking twice next time. I am sorry.