Невозможно запустить две команды выполнения миграции вместе в одной консольной команде

Для разработки у нас есть одна консольная команда Symfony, которая выполняет другие консольные команды для перестроения базы данных, запуска фикстур и т. д.

В рамках этого процесса мне нужно запустить несколько отобранных команд миграции доктрины, но по какой-то причине я не могу запустить несколько команд выполнения в одном процессе.

Чтобы подтвердить, я могу без проблем запускать эти задачи вручную и могу запускать одну из команд в консоли, а затем другую вручную без проблем.

          $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);

Возвращаемая ошибка:

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

Версия, являющаяся первым существующим файлом версии, может подтвердить, что ее нет в таблице migration_versions, и она не нужна в этом сценарии. Предполагая, что он просто загружен в объект миграции.

Может ли кто-нибудь предложить свой вклад, если я делаю что-то не так, возможно, это где-то ошибка.

Запуск Symfony 2.2.* и пакет миграций с помощью dev-master.


person MadManMonty    schedule 19.03.2014    source источник


Ответы (3)


У меня была такая же проблема в symfony 2.6 и решение, описанное Алексей Теницкий не работал, хотя казался допустимым. Это решение, которое сработало для меня.

/**
 * 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()));
        }
    }
}

если вы используете $this->getApplication()->run(), он возьмет команду из $this->application->commands, где команды инициализируются только один раз и (когда инициализируется вызов команды), поэтому MigrationsConfig останется неизменным на всех итерациях.

person HKristjan    schedule 29.12.2015

Проблема в том, что приложение использует один и тот же экземпляр команды для каждого вызова, а команды миграции Doctrine не предназначены для работы в такой среде. Один из способов обойти это — клонировать команду и работать с ее экземпляром напрямую:

$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)
person Alexei Tenitski    schedule 16.12.2014

Я предполагаю, что это потому, что вы пытаетесь запустить команду миграции несколько раз одновременно. Возможно, вы захотите попробовать использовать систему рабочих очередей, вероятно, есть даже пакет, который делает это.

person Tom Tom    schedule 19.03.2014
comment
Я посмотрю на очереди, чтобы увидеть, если это вариант. Мой текущий мыслительный процесс для решения этой проблемы заключается в использовании php exec, но это просто кажется неправильным и очень не подходит для Symfony. - person MadManMonty; 19.03.2014