Search code examples
phplaravellaravel-queue

Send an email after command has finished in Laravel


I have a command written on laravel which I wanna execute. It will take up at least 4 hours so I'd like to get an e-mail from the computer when the task is over. I'm using queues so I'd like to append the whole operation but I don't know if it's possible.

This is the current task:

public function handle()
    {

        $directory = 'pv';
        $files = Storage::allFiles($directory);
        foreach($files as $file)
        {
            $fname = basename($file);
            \Log::info('Procesando ',[$fname]);
            $arr = explode(" ", $fname);
            $day = substr($arr[2], 0, 10);
            $date = Carbon::parse($day);
            // this process goes to a queue in chunks
            Excel::queueImport(new POSImport($date), $file);
        }
    }

How do I append a new job that sends an e-mail after all is over? I'm not sure if I have to make a new command or a new job. I have the email job already tested and it works.

App\Jobs\SendMailFinished.php

public function handle()
    {
        //Sends message
        $me = '[email protected]';
        $msg = 'Process finished';
        Mail::to($me)->queue(new TasksFinished($msg));
    }

Solution

  • You can do this a number of different ways.

    Option 1

    Send the mail at the end of your handle method. This is the least complicated option:

    public function handle()
    {
    
        // job logic...
    
        Mail::to($me)->queue(new TasksFinished($msg));
    }
    

    Option 2

    Use withChain to chain the email job to be sent after the other job is successful:

    YourTask::withChain([
        new SendMailFinished
    ])->dispatch();
    

    Option 3

    Add an event listener for JobProcessed to EventServiceProvider.php:

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
    
        Queue::after(function (JobProcessed $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
    
            if ($was_my_job_class) {
                Mail::to($me)->queue(new TasksFinished($msg));
            }
        });
    }
    

    You can use this stackoverflow answer to determine if the processed job was the correct class.