roemer
5 months ago

Job never ends and keeps queue worker pinned at 100% CPU even though last line of handle() is reached

Posted 5 months ago by roemer

My application has several jobs to process uploaded CSV files. These files can be pretty big, so they are handled on a queue worker. All my jobs work fine, except for one, which never seems to finish. This job usually takes a little longer to process than the other ones, so I run the queue worker with php artisan queue:work --timeout=300 --sleep=3 so that the process does not automatically get killed. The job does not actually take 5 minutes, the max is about 1:30.

The weird thing though, is that it is not stuck on some infinite loop or something, the last line of the handle() method of the Job class is actually reached (it's a Log::info() which tells me that the job has finished). In the worker console Processed is never displayed and the thread is pinned at 100% CPU usage. Interestingly, the thread is at around 85% CPU while the job is running, and actually increases to 100% when it's finished. It won't actually run forever, when the --timeout which I supplied in the queue worker is reached, the process gets killed.

The job is initiated in the same way as any of the other jobs are (contextually):

// I use repository classes in my application, which are called from Controllers.
// In this case, the processFile method inside my ImportRepository dispatches the job that
// will process the file.
public function processFile(UploadedFile $file, string $type, $delimiter = ';') : Import
{
    // Each uploadable file has it's own class which defines the columns etc. This function
    // will initiate that class for the uploaded file. It also has information on which job
    // to call etc. which is used later
    $import = $this->getImportClassForType($file, $type);

    // Model is a Eloquent model to track the status, create it
    $model = $this->create([
        'type'      => $type,
        'started_on'    => Carbon::now(),
        'status'        => 'initiated',
        'line_count'    => $file->getLineCount(),
    ]);

    // Returns the specific job to dispatch to handle this type of file.
    $import::getValidationJobClass()::dispatch($import, $model);

    return $model;
}

The actual processing job is pretty simple, it has a foreach loop to iterate over the lines of the CSV file. I don't think the issue lies there, as this foreach loop is completed as expected and the final line of the processing Job is reached.

Could it have something to do with the fact that the job usually takes a little longer to process than any other? I had to use --timeout=300 because the queue process would get killed before. I can execute any other job with --timeout=300 and they will finish though... There are no errors in the logs. I just see the Log::info() from the last line and that's it. I tried adding return; to the Job class but no luck.

I use the latest Homestead on a MacBook Pro

Any help is appreciated.

Please sign in or create an account to participate in this conversation.