When adding an item to the queue, for some reason the handle method is not being called.
The Log entry in __construct is appearing but when attempting to log in handle(), nothing appears.
The method i'm using to dispatch is ProcessImport::dispatch($path, $task->task_id);
My queue service is configured to use Redis, and redis is storing all the data accordingly.
I am using Laravel 8. What could be wrong?
<?php
namespace App\Jobs;
use App\Models\Tasks;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Http\Controllers\Products\Products;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Queue;
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Queue\Events\JobProcessed;
use Throwable;
class ProcessImport implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $file_path;
protected $response;
protected $task;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($path, $task_id)
{
Log::info("Importing products (construct)");
$this->task = Tasks::where('task_id', $task_id)->first();
$this->file_path = $path;
Log::info('Importing ' . $path);
}
private function getFilePath() {
return $this->file_path;
}
/**
* Handle a job failure.
*
* #param \Throwable $exception
* #return void
*/
public function failed(Throwable $exception)
{
$this->task->failed($exception->getMessage());
}
/**
* Get the cache driver for the unique job lock.
*
* #return \Illuminate\Contracts\Cache\Repository
*/
public function uniqueVia()
{
return Cache::driver('redis');
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Log::info("Importing products (handle)");
$this->task->start();
$products = new Products();
$products->importProductsFromCSV($this->getFilePath());
$this->task->success();
Log::info("End of importing products..");
}
}
You've just pushed the jobs onto the queue but haven't started a worker to process them. You can run the worker with:
php artisan queue:work
Related
I'm working with one of my Laravel 8 API project's that I've built where a user is able to add a domain to their account. The domain needs to be crawled to obtain expiration dates etc and is available in the user's account.
This process takes some time and so I've extracted the logic that fetches the domain data into a job called DomainExpiryChecker.
When a new domain is added, a job is dispatched, but may not execute straight away, and in some cases the user may even delete the domain before the job runs.
For some reason, even after dispatching my job after a record has been made, I'm getting the following failed job error and I'm not sure what I'm missing:
Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\Models\Domains]
My controller where the job is dispatched resembles the following:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\User;
use App\Models\Domains;
use Carbon\Carbon;
use App\Jobs\DomainExpiryChecker;
class DomainsController extends Controller
{
/**
* Instantiate a new DomainsController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Add a new domain
*
* #param Request $request
* #return Response
*/
public function add(Request $request)
{
$domain = new Domains();
$domain->domain = '';
$domain->crawled = 'pending';
$domain->has_valid_ssl = false;
$domain->user_id = Auth::id();
$domain->save();
// on-demand
if ($domain) {
DomainExpiryChecker::dispatch($domain)->onQueue('on-demand-runs-now');
}
// everything went okay!
return response()->json(['success' => true, 'message' => "Added $domain_name successfully, please allow between 24 and 48 hours for crawling"], 201);
}
}
Whilst my job looks like the following:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use GuzzleHttp\Client;
use App\Models\Settings;
use App\Models\Domains;
use Carbon\Carbon;
class DomainExpiryChecker implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The domain instance.
*/
protected $domain;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($domain)
{
$this->domain = $domain;
}
/**
* Get single domain
*
* #return object
*/
public function getDomain($domain)
{
$domain = Domains::where('id', $domain['id'])
->first();
return $domain;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$updatableDomain = $this->getDomain($this->domain);
if (!$updatableDomain) {
return;
}
// stuff happens here
}
}
What am I missing, I'm sure it's just one thing.
I have a laravel job which I create from a controller and some times i want to delete those jobs as the timings will be rescheduled
It is a notification job which sends notification one hour before a class and if the class is rescheduled i need to delete the jobs and insert new ones
my controller code is as below
$job = (new OnlineClassRemainderJob($remainder_data))->delay($value);
$id = dispatch($job);
array_push($job_ids, $id);
and the Job class is as shown below
<?php
namespace App\Jobs;
use App\Mail\OnlineClassRemainderMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Mail;
class OnlineClassRemainderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $details;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Mail::to($this->details['email'])
->send(new OnlineClassRemainderMail($this->details));
}
}
Kindly show light how I can get the Job id so that i can save it in a database and in case of a reschedule i can remove all job ids related to that class and then dispatch new schedules
I can layout the scenario here
I am scheduling classes for example
I have a class on every day from 20th Jan to 25th Jan at 10 AM and I am scheduling a remainder mail sending job which will fire 1 hour before the class
But at certains scenario the Classes will be rescheduled and for that purpose i need to reschedule the remainders or delete and redispatch the jobs
you need to retrun job id from job with this function $this->job->getJobId();
class OnlineClassRemainderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Mail::to($this->details['email'])
->send(new OnlineClassRemainderMail($this->details));
retrun $this->job->getJobId();
}
}
then
$job = (new OnlineClassRemainderJob($remainder_data))->delay($value);
$id = dispatch($job);
array_push($job_ids, $id);
ref link https://laravel.com/api/8.x/Illuminate/Contracts/Queue/Job.html#method_getJobId
To take the id of a job before executing it, e.g. to dequeue it before executing it.
$log = UpdateLog::create();
UpdateProduct::dispatch($log)->delay(now()->addMinutes(10));
$regex = 'UpdateLog.*?id\\\\";i:'.$log->id.';';
//delete or get job before start
DB::table('jobs')->where('payload','REGEXP',$regex)->delete();
my job example
//...
class UpdateProduct implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* #var UpdateLog
*/
protected $log;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(UpdateLog $log)
{
$this->log = $log;
}
//...
}
I'm using Laravel with the protonemedia/laravel-ffmpeg package https://github.com/protonemedia/laravel-ffmpeg
I create a Job to handle video conversion and concatenation and this error appears:
TypeError: Argument 1 passed to App\Jobs\VideoConversion::App\Jobs{closure}() must be an instance of FFMpeg\Filters\Video\VideoFilters, instance of FFMpeg\Filters\AdvancedMedia\ComplexFilters given in /Users/fab/Sites/add-intro/app/Jobs/VideoConversion.php:43
Here is the code of the Job:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\Video;
use Storage, Str, ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;
use FFMpeg\Filters\Video\VideoFilters;
class VideoConversion implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $video;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(Video $video)
{
$this->video = $video;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$filename = Str::uuid().'.mp4';
FFMpeg::fromDisk('public')
->open(['intro.mp4', $this->video->path])
->addFilter(function (VideoFilters $filters) {
$filters->resize(new \FFMpeg\Coordinate\Dimension(640, 480));
})
->export()
->toDisk('public')
->inFormat(new \FFMpeg\Format\Video\X264)
->concatWithTranscoding($hasVideo = true, $hasAudio = true)
->save($filename);
}
public function failed(Throwable $exception)
{
FFMpeg::cleanupTemporaryFiles();
dd($exception);
}
}
What I'm doing wrong ?
Thanks for help
I am using the Laravel scheduler to run a job and if the job fails I want to write to the log and get sent an email. However as soon as I set it up even though the job was running fine I started getting emails and output in the log so for some reason Laravel is treating the job as if it's failed when it hasn't. Also if I look at the job in Telescope the status just stays on pending and never shows as complete or failed. I am using sync as my queue driver.
Here is my kernel.php file:
<?php
namespace App\Console;
use Log;
use App\Company;
use App\Jobs\ProcessPayments;
use App\Jobs\ProcessCompanyTiers;
use Illuminate\Console\Scheduling\Schedule;
use App\Jobs\ProcessPartialDiscountPayments;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
\App\Console\Commands\ProcessPartialDiscountPayments::class
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->job(new ProcessPartialDiscountPayments)
->onSuccess(function () {
Log::info('ProcessPartialDiscountPayments scheduled task successfully ran');
})
->onFailure(function () {
Log::info('ProcessPartialDiscountPayments errored and did not complete');
})
->emailOutputOnFailure(config('app.webmaster_email'));
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
/**
* Get the timezone that should be used by default for scheduled events.
*
* #return \DateTimeZone|string|null
*/
protected function scheduleTimezone()
{
return 'Europe/London';
}
}
And here is the job file:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Jobs\ProcessCompanyPayment;
use App\{ Company, DiscountCode };
use Log;
use Carbon\Carbon;
class ProcessPartialDiscountPayments
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $code_datetime;
protected $datetime_to;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
Log::info('Running ProcessPartialDiscountPayments');
$datetime = Carbon::now();
$this->code_datetime = $datetime->format('Y-m-d H:i');
$this->datetime_to = $datetime->format('Y-m-d H:i:s.v');
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$discount_codes = DiscountCode::whereRaw("left(convert(varchar(20), ValidTo, 120), 16) = '".$this->code_datetime."'")->get();
Log::info('Found '.$discount_codes->count().' discount codes');
if(!empty($discount_codes)) {
foreach($discount_codes as $discount_code) {
if($discount_code->companies->count() > 0) {
foreach($discount_code->companies as $company) {
$active_code = $company->discount_code($company->balance_at($this->datetime_to), $this->code_datetime);
if($active_code && $active_code->Id == $discount_code->Id) {
Log::info('Processing #'.$company->Id.': '.$company->Name);
ProcessCompanyPayment::dispatch($company, $this->datetime_to);
}
}
}
}
}
}
}
Here is the log entries that get generated when it runs:
[2019-12-19 12:32:03] local.INFO: Scheduler running
[2019-12-19 12:32:03] local.INFO: Running ProcessPartialDiscountPayments
[2019-12-19 12:32:03] local.INFO: Found 0 discount codes
[2019-12-19 12:32:03] local.INFO: ProcessPartialDiscountPayments errored and did not complete
Currently $discount_codes is always empty so the expected output should be that the handle function just writes to the log saying it hasn't found any and then the job completes.
I have created a very basic queue job:
<?php
namespace App\Jobs;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class FailingJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 1;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
// nothing
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
// nothing
}
/**
* Called when the job fails
*
* #param Exception $exception
*/
public function failed(Exception $exception) {
// nothing
}
}
and I dispatch it like so: FailingJob::dispatch();. This works fine.
Now I am purposefully adding "bugged" code in order for the job to fail, but instead of gracefully making the job fail,
I get the following exception:
Serialization of 'Closure' is not allowed.
I'm not sure where this is coming from, because this job is basically empty. I would like to use the failed() function in order to handle failures, but I can't even do that because this exception gets thrown when the job fails.
For reference, this is the code I use to make the job fail:
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
xxxxxx
// ^ This will make the job fail
}