I have a batch that calculates a score for many models. There is a horizon worker that process the batch, and most of the times, it runs with success.
However, sometimes, a job CalculateFieldScores
fails with the message No query results for model [Mz\Models\Ipa\Category]
.
The Category table in the database haven't change for more than a year, so it should always exist.
Here is the code.
CalculateCategoryScores
<?php
namespace Mz\Jobs\IPA;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Mz\Models\Ipa\Category;
use Illuminate\Support\Facades\Bus;
use Mz\Models\Ipa\Field;
class CalculateCategoryScores implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $categories;
private $fields;
public $timeout = 86400;
public function __construct()
{
$this->categories = Category::actives()->with('conditions')->get();
$this->fields = Field::actives()->with('conditions')->get();
}
public function handle()
{
foreach($this->categories as $category) {
$fields = $this->getFieldsByCategoryAssignation($category);
foreach($fields as $field) {
$batchable[] = new CalculateFieldScore($category, $field);
}
}
Bus::batch($batchable)
->then(function($batch) {
(new BuildTemporaryTables)->handle();
})
->dispatch();
}
private function getFieldsByCategoryAssignation($category)
{
return $this->fields->filter(function($field) use ($category) {
return $field->Assignation === 0 || $field->Assignation === $category->Assignation;
});
}
}
And this is the job thats sometimes fails:
<?php
namespace Mz\Jobs\IPA;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Mz\Models\Ipa\Category;
use DB;
use Mz\Models\Ipa\Field;
use Mz\Models\Ipa\FieldCategoryScore;
use Illuminate\Bus\Batchable;
class CalculateFieldScore implements ShouldQueue
{
use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $category;
private $field;
public $timeout = 86400;
public $backoff = 3;
public $tries = 3;
public function __construct(Category $category, Field $field)
{
$this->category = $category;
$this->field = $field;
}
public function handle()
{
$fileIdsQuery = $this->getFileIdsQuery($this->category, $this->field);
$avgCollection = $this->getAverageCollection($fileIdsQuery);
FieldCategoryScore::updateOrCreate([
'CategoryID' => $this->category->ID,
'FieldID' => $this->field->ID
], [
'AverageCollection' => $avgCollection,
'Score' => DB::raw($this->getFieldCategoryScore($avgCollection, $this->category) ?? 'null')
]);
}
...
}
Since the Category existed in CalculateCategoryScores and it was given in the constructor of CalculateFieldScore, how is it possible that the model is not found given that the table hasn't changed for more than a year?
Also, note that it is only attempted 1 times, even if I set the $tries
to 3.