I solved my problem using the Messenger component as @msg suggested in comments.
To do so, I had to:
- install the Messenger component by doing
composer require symfony/messenger
- create a custom log entity to track the file generation
- create a custom Message and a custom MessageHandler for my file generation
- dispatch the Message in my controller view
- move my command code to a service method
- call the service method in my MessageHandler
- run
bin/console messenger:consume -vv to handle the messages
Here is my code:
Custom log entity
I use it to show in my views if a file is being generated and to let the user download the file if its generation is complete
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\MyLogForTheBigFileRepository")
*/
class MyLogForTheBigFile
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="datetime")
*/
private $generationDateStart;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $generationDateEnd;
/**
* @ORM\Column(type="string", length=200, nullable=true)
*/
private $filename;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User")
* @ORM\JoinColumn(nullable=false)
*/
private $generator;
public function __construct() { }
// getters and setters for the attributes
// ...
// ...
}
Controller
I get the form submission and dispatch a message which will run the file generation
/**
* @return views
* @param Request $request The request.
* @Route("/generate/big-file", name="generate_big_file")
*/
public function generateBigFileAction(
Request $request,
MessageBusInterface $messageBus,
MyFileService $myFileService
)
{
// Entity manager
$em = $this->getDoctrine()->getManager();
// Creating an empty Form Data Object
$myFormOptionsFDO = new MyFormOptionsFDO();
// Form creation
$myForm = $this->createForm(
MyFormType::class,
$myFormOptionsFDO
);
$myForm->handleRequest($request);
// Submit
if ($myForm->isSubmitted() && $myForm->isValid())
{
$myOption = $myFormOptionsFDO->getOption();
// Creating the database log using a custom entity
$myFileGenerationDate = new \DateTime();
$myLogForTheBigFile = new MyLogForTheBigFile();
$myLogForTheBigFile->setGenerationDateStart($myFileGenerationDate);
$myLogForTheBigFile->setGenerator($this->getUser());
$myLogForTheBigFile->setOption($myOption);
// Save that the file is being generated using the custom entity
$em->persist($myLogForTheBigFile);
$em->flush();
$messageBus->dispatch(
new GenerateBigFileMessage(
$myLogForTheBigFile->getId(),
$this->getUser()->getId()
));
$this->addFlash(
'success', 'Big file generation started...'
);
return $this->redirectToRoute('bigfiles_list');
}
return $this->render('Files/generate-big-file.html.twig', [
'form' => $myForm->createView(),
]);
}
Message
Used to pass data to the service
namespace App\Message;
class GenerateBigFileMessage
{
private $myLogForTheBigFileId;
private $userId;
public function __construct(int $myLogForTheBigFileId, int $userId)
{
$this->myLogForTheBigFileId = $myLogForTheBigFileId;
$this->userId = $userId;
}
public function getMyLogForTheBigFileId(): int
{
return $this->myLogForTheBigFileId;
}
public function getUserId(): int
{
return $this->userId;
}
}
Message handler
Handle the message and run the service
namespace App\MessageHandler;
use App\Service\MyFileService;
use App\Message\GenerateBigFileMessage;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
class GenerateBigFileMessageHandler implements MessageHandlerInterface
{
private $myFileService;
public function __construct(MyFileService $myFileService)
{
$this->myFileService = $myFileService;
}
public function __invoke(GenerateBigFileMessage $generateBigFileMessage)
{
$myLogForTheBigFileId = $generateBigFileMessage->getMyLogForTheBigFileId();
$userId = $generateBigFileMessage->getUserId();
$this->myFileService->generateBigFile($myLogForTheBigFileId, $userId);
}
}
Service
Generate the big file and update the logger
public function generateBigFile($myLogForTheBigFileId, $userId)
{
// Get the user asking for the generation
$user = $this->em->getRepository(User::class)->find($userId);
// Get the log object corresponding to this generation
$myLogForTheBigFile = $this->em->getRepository(MyLogForTheBigFile::class)->find($myLogForTheBigFileId);
$myOption = $myLogForTheBigFile->getOption();
// Generate the file
$fullFilename = 'my_file.pdf';
// ...
// ...
// Update the log
$myLogForTheBigFile->setGenerationDateEnd(new \DateTime());
$myLogForTheBigFile->setFilename($fullFilename);
$this->em->persist($myLogForTheBigFile);
$this->em->flush();
}