I want a job A to dispatch another job B, where job B will be validating data from the database in chunks.
Job A
/**
* Handle the event.
*
* @param BatchPersisted $event
* @return void
*/
public function handle(BatchPersisted $event)
{
if ($this->attempts() > 1) {
logger('Validation Job Failed!');
$this->fail();
}
$batch = $event->getBatch();
$batch->updateStatus(Batch::STATUS_VALIDATING);
logger('Batch Uploaded Listened: Now Validating');
foreach (Batch::$ENTITIES_NAME as $entity_name => $entity_class_name) {
// $this->validateEntity($entity_class_name, $batch, $entity_name);
dispatch(new EntityValidationJob($batch));
}
event(new BatchValidated($batch));
}
then Job B
<?php
namespace App\Jobs;
use App\Batch;
use App\Instalment;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class EntityValidationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $validator;
/**
* @var Batch
*/
private $batch;
/**
* @var
*/
private $entity;
/**
* Create a new job instance.
*
* @param Batch $batch
* @param string $entity
*/
public function __construct(Batch $batch, $entity = 'LoanRelation')
{
$this->validator = app('validator');
$this->batch = $batch;
$this->entity = $entity;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$entity_class_name = Batch::$ENTITIES_NAME[$this->entity];
/** @var Builder $model */
$raw_model = app($entity_class_name);
$model = call_user_func_array([$raw_model, 'whereBatchId'], [$this->batch->id]);
$total = $model->count();
$generator = $model->cursor();
$error_count = 0;
/** @var Instalment $item */
foreach ($generator as $item) {
$validator = $this->validator->make($item->toArray(), $raw_model::rules());
// The respective loan / customer code ..
$code = $item->detectIfLoanOrCustomerCode();
// if a record/row passes, update pass column to true
// if it fails, update error table with id, code (customer/loan), errors (in json)
if ($validator->fails()) {
$item->errata()->delete();
$item->errata()->create([
'code' => ($code) ? $code : 'Not Provided',
'entity' => $this->entity,
'batch_id' => ($this->batch)->id,
'errors' => $validator->errors()->toJson(),
]);
$item->update(['pass' => 0]);
$error_count++;
} else {
// Update the row as pass!
$item->update(['pass' => 1]);
// TODO Go through every entity that needs to validate presence in the parent file.
// TRY THIS MF!
$item->validatingDependencies();
}
// log the progress of the app
logger(class_basename($item) . ' ...: ' . ($generator->key() + 1) . '/' . $total . " (Errors: $error_count)");
}
// log the progress of the file name
logger("Validated:- Batch name: {$this->batch->name} Entity Name: {$raw_model->getTable()}");
}
}
This produce the below error.
Serialization of 'Closure' is not allowed {"exception":"[object] (Exception(code: 0): Serialization of 'Closure' is not allowed at /Users/leyluj/projects/akili_works/mikopo/vendor/laravel/framework/src/Illuminate/Queue/Queue.php:128)
Don't do $this->validator = app('validator');
, laravel will try to serialize all job class properties, this will cause many issues, one important con also is a bigger job payload which sqs will compain about for example.
Most helpful comment
Don't do
$this->validator = app('validator');
, laravel will try to serialize all job class properties, this will cause many issues, one important con also is a bigger job payload which sqs will compain about for example.