Skip to content

Using --profile on a command with run() overriden #61134

@elavrom

Description

@elavrom

Symfony version(s) affected

Seen in 7.1, still there in 7.4

Description

Hi there !

I have a particular use case for several commands in my project where I want to run the same command multiple times based on different contexts (i.e. switching databases).

In order to do so, I've added an AbstractLoopCommand layer where I've overriden the run() function to loop through contexts and then execute the command.

The problem is that when I want to use --profiler for debugging, the TraceableCommand interferes and does not call my overriden run() function.

How to reproduce

I haven't tested it but it's mostly copy/pasted from my project, so it should reproduce my issue.
If needed, I'll try to make a full reproducer project later on.

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

abstract class AbstractLoopCommand extends Command
{
    public function run(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        $contexts = [1, 2, 3];

        $io->progressStart(count($contexts));

        $results = [];
        $code = self::SUCCESS;
        foreach ($contexts as $context) {
            $io->progressAdvance();

            //$this->switchContext($context);

            try {
                $results[] = [$context, parent::run($input, $output)];
            } catch (\Throwable $e) {
                $code = self::FAILURE;
                $results[] = [$context, $e->getMessage() . PHP_EOL . $e->getTraceAsString()];
            }
        }
        $io->progressFinish();
        // print the result
        return $code;
    }
}
namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand('app:loop:example')]
class LoopExampleCommand extends AbstractLoopCommand
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->text('Hello world');
        return Command::SUCCESS;
    }
}

Then try to run symfony console app:loop:example --profile. The command will not execute the AbstractLoopCommand::run() so no progressBar will be shown, and a single HelloWorld will be output.

Possible Solution

To resolve my issue locally, I've changed the following line :

$this->exitCode = parent::run($input, $output);

to :

            $this->exitCode = $this->command->run($input, $output);

TBH, I have no idea if it breaks something elsewhere, but it fixes my issue and I can now have a profile of my looping command.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions