Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

eggplantSword's avatar

Using Job Events

I need to keep track of the jobs and save the jobs that are completed in a db table. So that I can then send a user notification. This is my table structure.

Schema::create('job_requests', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id')->unsigned();
    $table->dateTime('request_time');
    $table->boolean('completed');
    $table->foreign('user_id')->references('id')->on('users');
});

Schema::create('job_request_reports', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('request_id')->unsigned();
    $table->integer('survey_id')->unsigned();
    $table->boolean('processed');
    $table->foreign('request_id')->references('id')->on('job_requests');
    $table->foreign('survey_id')->references('id')->on('surveys');
});

This is where I'm dispatching the jobs and also creating instances of the tables above

if (count($report) > 0) {
    $job_request = new JobRequest();
    $job_request->user_id = auth()->user()->id;
    $job_request->request_time = $now;
    $job_request->completed = false;
    $job_request->save();

    foreach ($report as $item) {
        $this->dispatch(new DownloadReport($item));

        $request_reports = new JobRequestReport();
        $request_reports->request_id = $job_request->id;
        $request_reports->survey_id = $item->id;
        $request_reports->processed = false;
        $request_reports->save();
    }
}

My questions is how can I use the Job Events to keep track of when the job was successful? How can I check for this?

Queue::after(function (JobProcessed $event) {
    // $event->connectionName
    // $event->job
    // $event->job->payload()
});
0 likes
10 replies
Snapey's avatar

make the job itself responsible for updating the table or issuing an event, which is then heard by a listener that then updates the jobs table.

You would need to pass the jobs table reference to your queued job.

eggplantSword's avatar

@snapey I am updating in the job, it creates an excel file and when I check that the excel has been created I'm updating the table. How can I check my table to see when all the jobs have been marked as completed?

Snapey's avatar

why not put a 'finish' job on the queue after you load all the processing jobs?

eggplantSword's avatar

@snapey ok I added a new CheckIfDone Job and I'm going to pass the $job_request->id so then search for the JobRequestReports that belong to check and see if they're all set as processed = true. Right now there is a job that is always going to fail because there is an error in the data so how can I basically see if the failed job is because of that error and ignore it. Or what do you recommend I do in that case?

This is the job I made, this works only if no jobs failed so I'm not sure what to do if a job fails

class CheckIfDone implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

    public function handle()
    {
        $reports = JobRequestReport::where('request_id', $this->id)
            ->where('processed', false)->count();

        if ($reports == 0) {
            $job_request = JobRequest::findOrFail($this->id);
            $job_request->completed = true;
            $job_request->save();

            $user = User::findOrFail(JobRequest::findOrFail($this->id)->user_id);
            $user->notify(new QueueDone());
        }
    }
}

This also notifies the user that they can request a download method to be executed, what should I do if one of the jobs fails and the if is false?

Snapey's avatar

Without looking into too much detail of what you have so far...

I was thinking along the lines of

for each file that needs to be processed, create a tracking record in a jobs table. Throw the work onto the queue. then when all jobs on the queue put another job on the queue that runs after all the others and checks the status and final outcome.

When each queued job is run, it marks its outcome on its associated tracking record (pass or fail)

When the final job runs, it can check the tracking table to see if all the jobs in that batch were successful and can report it to the user somehow.

Alternatively, the client can poll the database checking the status of all the jobs and display something to the user when they are all complete.

I mentioned the 'batch'. When you start this process, create a batch number that associates all jobs together so that you can report on the outcome of that batch.

eggplantSword's avatar

@snapey What I have is very similar to your suggestion, I do track each job and see if it was completed or not and save that to a table, after all the jobs get dispatched I dispatch another job that checks the db records and sees if all the jobs were set to success and if they are then it sends a notification to the user but ONLY when all the jobs were successful, what should I do if there are jobs that failed?

Right now if there are failed jobs the user doesn't get notified at all since technically the batch is not complete. Should I still notify the user even though some of the jobs failed?

Snapey's avatar

It depends if there is any chance that the work is still being performed when you do the final check?

If you are confident that the final outcome is ready (ie, set all to 'pending' and then 'success' or 'fail') then I guess its a business decision how you handle it (not a technical decision). If you know one job will fail, why schedule it?

eggplantSword's avatar

@snapey Well the jobs depend on data from the server, it's a excel file for a survey, if a question answer didn't get saved (still have no idea how that happened) then the job will fail because the excel can't be created off incomplete data, in the excel I do % so it creates a can't divide by 0 error and the job fails. Maybe there is a way to fix that so that the entire job doesn't fail and maybe the excel just skips that question, I'm not sure.

The way the jobs get dispatched is with a foreach so for each corresponding survey a job gets created regardless of correct data or not, there is no way for me to tell if the job will be successful or not.

How can I make sure the finishing Job is done after everything else? I'm dispatching them like this so ideally it would always be the last job

if (count($report) > 0) {
    foreach ($report as $item) {
        $this->dispatch(new DownloadReport($item));
    }

    $this->dispatch(new CheckIfDone());
}
Snapey's avatar

If there are no reports still in pending state then its complete?

eggplantSword's avatar

@snapey Yea, well I have my table a column that's a boolean for processed, at first it's set to false, and when the job is complete (excel is created) I set processed to true, so at the end I check if all the processed columns are true

Please or to participate in this conversation.