Reputation: 373
I have a symfony app in which I need to send an email asynchronously. When my users perform certain action I need to send an email to the admin. For that I've created a symfony custom command to use with Symfony Process Component, which is similar to php native's exec(). My code is as follows:
if ($trigger == true) {
$command = 'php bin/console async-email';
$process = new Process([$command]);
$process->start();
$pid = $process->getPid();
}
According to the official documentation this should be enough, but I can confirm the email isn't being sent. However when I for the threat to wait for the command to end (as in not async) and print the result the command works perfectly and the email gets sent.
$process->wait(function ($type, $buffer) use ($data) {
// do stuff
});
return new JsonResponse([$process->getErrorOutput(), $process->getOutput(), $pid]);
I've also tried:
Any approach works but NOT asynchronously. What I need is for the command to perform the action on the background and not interfere with the normal code execution.
Upvotes: 0
Views: 157
Reputation: 373
You're 100% correct about symfony process component behavior @Łukasz Jakubek. You can run n async child proceses (from each other) but they're main process dependant so if you don't wait or check for completion they're killed when main execution ends.
I had not quite grasped the difference between asynchromous and background. So after the recomendation given above by Julien B. I realized that a quequing system was what I needed, so I spent the last 12 hours refactoring my code to use symfony messenger with doctrine transport and voilá, works like a charm!
Might have to look a more advance quequing system in the future like RabbitMQ which allows dynamic asynchronous queques.
For now my problem is solved and more important I'm on the right direction, thanks a lot!
Upvotes: 0
Reputation: 1013
First, If You start some async process from main process, Youe need to wait until all async processes complete before end main process. In other case, when main process is closed, all async child processes are killed before end their tasks. This is general rule for any app.
So if You do not want to wait for e-mails sent, add mail to queue, and finish main request. Then run php bin/console async-email
from corn
i.e. on every 5min. This will async.
But IMHO, if user send single e-mail after some (not every) action performed, it's totally fine to send this email synchronously from controller action.
Upvotes: 1