@ChangeSet executed before @ChangeUnit, ignoring order
EfreetSK opened this issue · comments
Description
When having a project with both @ChangeSet
and @ChangeUnit
, the @ChangeUnit
is executed first, ignoring order.
We started using Mongock in the version 4 so we have a legacy @ChangeSets
in our code. As suggested on a migration page, we kept existing @ChangeSets
as they are and started using @ChangeUnit
instead for future changes. However, when our QA department needed to re-create the database, the execution fails because the new changes (ChangeUnits) were executed first
PRIORITY
NORMAL
Version and environment
Mongock
- Mongock version: 5.3.4
- Modules involved: springboot, webflux, standalone, MongoDB, mongodb-sync-v4-driver,
- How Mongock is used(builder or annotation approach, etc.): not sure how to answer, we use annotations, check demo project
Environment
- Framework and libraries versions. Especially those that affect directly to Mongock(Spring, Spring data, MongoDB driver, etc.)
- org.springframework.boot: 3.1.3
- spring-webflux: 6.0.11
- spring-data-mongodb: 4.1.3
- Java 17.0.8.1
- mongodb driver: 4.9.1
- Infrastructure: plain Java application
Steps to Reproduce
- Create a
@ChangeLog
with@ChangeSet
, set it order 0001 - Create a
@ChangeUnit
, set it order 0002 - Start the application
- Application crashes because the
@ChangeUnit
was executed first and order was ignored. Example exception:
io.mongock.api.exception.MongockException: io.mongock.api.exception.MongockException: Error in method[DatabaseChangeLog.myFirstChangeLog] : Command failed with error 48 (NamespaceExists): 'Collection already exists. NS: testing-mongock.helloMongock' on server 127.0.0.1:27017. The full response is {"ok": 0.0, "errmsg": "Collection already exists. NS: testing-mongock.helloMongock", "code": 48, "codeName": "NamespaceExists", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1697099934, "i": 5}}, "signature": {"hash": {"$binary": {"base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType": "00"}}, "keyId": 0}}, "operationTime": {"$timestamp": {"t": 1697099934, "i": 5}}}
Behaviour
I'd expect that legacy @ChangeLogs
and new @ChangeUnits
can coexist, respecting each others order
Actual behavior: [What actually happens]
It looks like @ChangeUnits
are executed first and order isn't respected
Link to repository using Mongock
I created a simple project to reproduce this:
https://github.com/EfreetSK/mongock-issue
Additional context
As far as I know this wasn't an issue before, we have other project which mixes @ChangeLog and @ChangeUnit. But it's been some time ago since we tried to recreate the whole database so maybe we just didn't notice.
Notice that we are using some adaptions in RootApplicationContext but hopefully this shouldn't be related to this
Hello @EfreetSK , this seem an important one. We'll take a look shortly.
Hello @EfreetSK , after review your provided project and the Mongock's current behaviour, the fix for your project is setting the order
in the legacy @ChangeLog
annotation, this way:
@ChangeLog(order = "0001")
public class DatabaseChangeLog {
@ChangeSet(order = "0001", id = "0001", author = "test")
public void myFirstChangeLog(MongoDatabase db) {
db.createCollection("helloMongock");
}
}
Note that the order should be lower than the order of your new @ChangeUnit
classes (alphabetical order).
If you have multiple ChangeLog classes, please ensure that you set the order attribute in all of them.
Please let us know if it works for you.
We will update documentation to clarify the upgrade to v5 guide.
Many thanks.
@osantana85 Thank you for your reply. You're right, setting the order of @ChangeLog
solves my issue, thank you!
Maybe for others who are reading this, I was wondering what should be the order of @ChangeUnit
if there are multiple @ChangeSets
. So f.e. let's have a @ChangeLog
like this
@ChangeLog(order = "0001")
public class DatabaseChangeLog {
@ChangeSet(order = "0001", id = "0001", author = "test")
public void myFirstChangeSet(MongoDatabase db) {
db.createCollection("helloMongock");
}
@ChangeSet(order = "0002", id = "0002", author = "test")
public void mySecondChangeSet(MongoDatabase db) {
db.createCollection("mySecondCollection");
}
}
And I was wondering what should be the @ChangeUnit
order now, 0002 (as a second class to be executed) or 0003 (as a third 'change set' to be executed). I tried it and the answer is 0003
@ChangeUnit(id="0003", order = "0003", author = "test")
public static class MyFirstChangeUnit {