Skip to content

Cannot write integration test: 'Lock cannot be acquired after being cancelled' (regression since Mongock 4) #144

@pkubowicz

Description

@pkubowicz

Description

I write integration tests of migrations written using Mongock: I execute them using MongockApplicationRunner.
What works in Mongock 4 crashes in Mongock 5. During Spring context load, Mongock enters a state where it refuses to run any further migrations.

PRIORITY

NORMAL

Version and environment

Mongock

  • Mongock version: 5.0.36
  • mongock-springboot + mongodb-springdata-v3-driver
  • annotation approach

Environment

  • Spring Boot 2.6.4
  • Infrastructure: JUnit Jupiter + Spring Test

Steps to Reproduce

  1. Write a @SpringBootTest
  2. Let Spring inject MongockApplicationRunner into your test
  3. Use MongockApplicationRunner to execute your migration

Behaviour

Expected behavior: Mongock runner executes my migration

Actual behavior: Runner does not even start, it crashes on acquiring lock:

2022-03-02 20:20:52.237 ERROR 81672 --- [    Test worker] i.m.r.core.executor.MongockRunnerImpl    : Mongock did not acquire process lock. EXITING WITHOUT RUNNING DATA MIGRATION

io.mongock.driver.api.lock.LockCheckException: Lock cannot be acquired after being cancelled
	at io.mongock.driver.core.lock.LockManagerDefault.initialize(LockManagerDefault.java:374) ~[mongock-driver-core-5.0.36.jar:na]
	at io.mongock.driver.core.lock.LockManagerDefault.acquireLockDefault(LockManagerDefault.java:145) ~[mongock-driver-core-5.0.36.jar:na]
	at io.mongock.runner.core.executor.operation.change.MigrationExecutorBase.executeMigration(MigrationExecutorBase.java:96) ~[mongock-runner-core-5.0.36.jar:na]
	at io.mongock.runner.core.executor.operation.change.MigrationExecutorBase.executeMigration(MigrationExecutorBase.java:46) ~[mongock-runner-core-5.0.36.jar:na]

The exception is misleading: nothing is ever cancelled. The previous run of Mongock (during Spring context load) finishes successfully.

io.mongock.driver.core.lock.LockManagerDefault#initialize documentation claims the method is 'idempotent'. Of course it isn't because it starts with:

    if (releaseStarted) {
      throw new LockCheckException("Lock cannot be acquired after being cancelled");
    }

releaseStarted is only set to true, never set to false. This means in Mongock 5, the lock manager becomes useless the moment after it's started for the first time. There is no way to correctly use it again.

How often the bug happens: Always

Link to repository using Mongock

https://github.com/pkubowicz/mongock5-springboot-test

A GitHub action proves that 100% identical code works in Mongock 4 but crashes in Mongock 5.

Additional context

Maybe this is not the most effective way of testing a migration, but the Mongock documentation does not offer any advice. Since my real-life system is built on Spring Boot, it seems logical to write tests in Spring Boot way. I have to control running migrations in my test, because I need to save initial state into the database.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions