@Override
  public void startIt() {
    if (semaphore.tryAcquire()) {
      try {
        executorService.execute(this::doDatabaseMigration);
      } catch (RuntimeException e) {
        semaphore.release();
        throw e;
      }
    } else {
      LOGGER.trace("{}: lock is already taken or process is already running", Thread.currentThread().getName());
    }
  }
@Test
  public void successive_calls_to_startIt_reset_status_startedAt_and_failureError() {
    mockMigrationThrowsError();

    underTest.startIt();

    assertThat(migrationState.getStatus()).isEqualTo(DatabaseMigrationState.Status.FAILED);
    assertThat(migrationState.getError()).get().isSameAs(AN_ERROR);
    assertThat(migrationState.getStartedAt()).isPresent();
    Instant firstStartDate = migrationState.getStartedAt().get();

    mockMigrationDoesNothing();

    underTest.startIt();

    assertThat(migrationState.getStatus()).isEqualTo(DatabaseMigrationState.Status.SUCCEEDED);
    assertThat(migrationState.getError()).isEmpty();
    assertThat(migrationState.getStartedAt())
      .get()
      .isNotSameAs(firstStartDate);
  }