15

in Laravel, you can use jobs to execute tasks in a back-end queue while the rest of the application does other things. i have a job that is initiated by user input. immediately, through javascript, i give the user a notification that the job is being processed.

i would like to be able to give a similar notification after the job has successfully completed.

i am calling my job from within a model like this:

public function doSomething() {
    $job = new \App\Jobs\MyJob();
    app('Illuminate\Contracts\Bus\Dispatcher')->dispatch($job);
}

and this is how my job headers look like:

class MyJob extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels, Queueable;
    ...
}

the model job call is actually triggered from a controller method:

public function getDoSomething($id) {
    $item = Item::findOrFail($id);
    $item->doSomething();

    return response()->json(true);
}

which is handled by an AJAX call:

$.ajax({
    url: $(this).attr('href'),
    type: 'GET',
    dataType: 'json',
    success: $.proxy(function(result) {
        this.application.notification.showMessage('Job is being processed.');
    }, this),
    error: $.proxy(function(result) {
        console.error(result);
    }, this)
});
szaman
  • 2,159
  • 1
  • 14
  • 30
  • With Jobin's answer: I think you could store in session the new job (generating a random hash): `$_SESSION('sd23f32r') = array('hasFinished'=>false);` and when it finishes you update the value, and your js can make 'pings' to check if the job finished (read session data). I wouldn`t save in a table because there would be too many hits – ka_lin Feb 11 '16 at 10:58

4 Answers4

7

You can user Queue::after function on your AppServiceProvider

Import this dependencies

use Illuminate\Support\Facades\Queue;
use Illuminate\Queue\Events\JobProcessed;
use Illuminate\Queue\Events\JobProcessing;

And on boot method you would use it

public function boot()
    {
        Queue::before(function (JobProcessing $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
        });

        Queue::after(function (JobProcessed $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
        });
    }
Leandro Castro
  • 241
  • 2
  • 13
5

Probably I'm late for the party guys, but there are several options i can think of. When user clicks button from the front-end you can give attribute disabled to it and some text like 'processing'. Then you can:

  1. Just ping your endpoint to check if what job is performing is finished
  2. Use websockets

I think Forge is doing websockets using pusher the endpoint to see if server is active when you are trying to deploy new code. I can clearly see the communication if you open Devtools->Resources->Sockets.

linkmarine
  • 93
  • 2
  • 8
  • 3
    unlike the other answers, yours actually answers the question, which is about how to notify the user on the frontend. if you expand it a bit (like, providing some code showing how to ping the server for that info), and explain how to know when the job is finished on the backend (other answers explain that), it will be a great answer, and i will accept it. – szaman Mar 21 '19 at 22:37
4

You can use queue events, Laravel document explains it: https://laravel.com/docs/5.6/queues#job-events

Amirmasoud
  • 590
  • 4
  • 11
  • 27
  • 1
    this answer only explains how to detect that a job has finished on the backend, not how to notify the frontend user. – szaman Mar 21 '19 at 22:33
  • @rrrafalsz For that matter, one solution can be Laravel Echo https://laravel.com/docs/5.6/broadcasting#installing-laravel-echo – Amirmasoud Aug 26 '19 at 03:57
1

Job Completion Event

The Queue::after method allows you to register a callback to be executed when a queued job executes successfully. This callback is a great opportunity to perform additional logging, queue a subsequent job, or increment statistics for a dashboard.

This already in the page link you shared from Laravel.

Jobin
  • 8,238
  • 1
  • 33
  • 52
  • 3
    This does not explain how to send a message to the user, i.e. the same thread which sent the job in the first place. All the examples given are about something to happen in the background again. – Paranoid Android Jul 26 '17 at 11:52
  • I think that is the point though, for example, I am dispatching a job to generate an archive of user files, then on completion, I email the user with a link to download the archive. – Paranoid Android Feb 01 '18 at 13:15