1

I'm running a spring boot 2.4.3 app and I have a mongodb 4 cluster which supports transactions(I run it locally using run-rs). I'm also using spring data mongodb. I'm trying to integrate mongock(latest version - 4.3.8) for db migrations but I face a problem, which I can't resolve. As we know the the latest version of mongock is using transactions by default. I have the following changeset which just creates a mongodb collection for one of my entities.

@ChangeSet(order = "001", id = "initSessionCollection", author = "Hristo")
public void init(MongockTemplate mongockTemplate) {
  mongockTemplate.createCollection(Session.class);
}

When I run the application the migration fails with the following error:

2021-04-13 16:36:18.092  WARN 70141 --- [           main] c.g.c.m.d.m.s.v.SpringDataMongoV3Driver  : Error in Mongock's transaction

com.github.cloudyrock.mongock.exception.MongockException: Error in method[InitDb.init] : Command failed with error 251 (NoSuchTransaction): 'Given transaction number 1 does not match any in-progress transactions.' on server localhost:27017. The full response is {"errorLabels": ["TransientTransactionError"], "operationTime": {"$timestamp": {"t": 1618320977, "i": 3}}, "ok": 0.0, "errmsg": "Given transaction number 1 does not match any in-progress transactions.", "code": 251, "codeName": "NoSuchTransaction", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1618320977, "i": 3}}, "signature": {"hash": {"$binary": {"base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType": "00"}}, "keyId": 0}}}; nested exception is com.mongodb.MongoCommandException: Command failed with error 251 (NoSuchTransaction): 'Given transaction number 1 does not match any in-progress transactions.' on server localhost:27017. The full response is {"errorLabels": ["TransientTransactionError"], "operationTime": {"$timestamp": {"t": 1618320977, "i": 3}}, "ok": 0.0, "errmsg": "Given transaction number 1 does not match any in-progress transactions.", "code": 251, "codeName": "NoSuchTransaction", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1618320977, "i": 3}}, "signature": {"hash": {"$binary": {"base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType": "00"}}, "keyId": 0}}}

If I disable transactions for mongock as expected the migration is applied successfully. I don't want to disable transactions for db migrations but I can't figure out where is the problem.

EDIT: I found out what the problem is- because Spring boot is embracing multi document transactions and the create collection command is not supported in such transactions. But then how should I handle the creation of a collection?

Hristo Angelov
  • 1,019
  • 1
  • 15
  • 34

1 Answers1

2

As you have mentioned, MongoDB transaction model has some limitations. Please see official MongoDB documentation.

Having that into account, you cannot wrap that operation in a transaction, so you cannot use it in a standard ChangeLog, if you are using transactions.

However, the good new i that, as always :D, Mongock team thought about it and will provide a mechanism for pre-transactions operations.

We expect to have a release candidate ready around June. However, if this is an urgent need, please send us an email to dev@cloudyrock.io and we'll try to find a solution.

Mongock team
  • 1,188
  • 5
  • 9
  • Okay, thanks. My problem is that all insert operations as you can expect are in a transaction and that's why the collection can't be created automatically when inserting a new document. But I found out a way to create the collections by enabling index auto creation, which as expected creates the collections. Apart from that I'm not in a rush for the feature you develop, but it's a nice one and I'll wait for it. – Hristo Angelov Apr 15 '21 at 12:55