Unable to run two migration execute commands together within a single console command
Asked Answered
B

3

5

For development we have a single Symfony console command that executes other console commands in order to rebuild db, run fixtures etc.

As part of the process I need to run a few cherry-picked doctrine migration commands, but for some reason I'm unable to run multiple execute commands within the same process.

To confirm, I can run these tasks without issue manually, and can run one of either command within the console execute and then the other manually without issue.

          $this->getApplication()->run(new ArrayInput(array(
            'command' => 'doctrine:migrations:execute',
            'version' => '20140310162336',
              '--no-interaction' => true
                )), $output);

          $this->getApplication()->run(new ArrayInput(array(
            'command' => 'doctrine:migrations:execute',
            'version' => '20140310170437',
              '--no-interaction' => true
                )), $output);

The error returned is:

[Doctrine\DBAL\Migrations\MigrationException]
Migration version 20140310162334 already registered with class Doctrine\DBAL\Migrations\Version

The version being the first version file that exists, can confirm that one is not in the migration_versions table, nor is it wanted in this scenario. Suggesting it is just loaded into the migrations object.

Can anyone offer input if I'm doing something wrong of if this is perhaps a bug somewhere.

Running Symfony 2.2.* and migrations bundle using dev-master.

Bellyband answered 19/3, 2014 at 13:53 Comment(0)
S
5

I had the same problem on symfony 2.6 and the solution described by Alexei Tenitski didn't work althought it seemed a valid one. This is the solution that worked for me.

/**
 * Loop thorugh the config and path config for migrations 
 * and execute migrations for each connection
 */
foreach (array_keys($this->migrationsConfig) as $configEm) {
    if (
        (empty($ems) || in_array($configEm, $ems))
        && !in_array($configEm, $ignoreEms)
    ) {
        try {
            // new instance of the command you want to run 
            // to force reload MigrationsConfig
            $command = new MigrateSingleCommand($this->migrationsConfig);
            $command->setApplication($this->getApplication());
            $arguments = [
                'command' => $commandString,
                '--em' => $configEm,
            ];
            $input = new ArrayInput($arguments);

            $command->run($input, $output);

        } catch (\Exception $e) {
            $output->writeln(sprintf("<error>Error: %s</error>", $e->getMessage()));
        }
    }
}

if you use $this->getApplication()->run() it will take the command from $this->application->commands where the commands are initialized only once and (when the command calling is initialized) so the MigrationsConfig will stay the same on all iterations.

Shoelace answered 29/12, 2015 at 13:18 Comment(0)
B
4

The problem is that application uses same instance of command for each call and Doctrine migrate commands are not designed to work in such environment. One way to work around it is to clone command and work with its instance directly:

$commandName = 'doctrine:migrations:execute';

$prototypeCommand = $this->getApplication()->get($commandName);

// This is required to avoid merging of application definition for each cloned command
$prototypeCommand->mergeApplicationDefinition();

// Create a clone for a particular run
$command1 = clone $prototypeCommand;

// Run the command with specific params
$command1->run($input1, $output)

// Create another clone
$command2 = clone $prototypeCommand;

// Run the command with another set of params
$command2->run($input2, $output)
Bodine answered 16/12, 2014 at 19:28 Comment(0)
R
0

My guess is that it is because you are trying to run the migration command multiple times at once. You might want to try using a work queue system, there is probably even a bundle that does that.

Repetitious answered 19/3, 2014 at 14:31 Comment(1)
I will look into queues to see if that is an option. My current thought process to solve this issue is to use php exec, but that just feels wrong and very much not a Symfony way to do things.Bellyband

© 2022 - 2024 — McMap. All rights reserved.