I am currently running Horizon using Redis on my Homestead VM.
I have an example queueable mailable that looks a bit like this:
<?php
namespace App\Mail;
// ... imports ...
class WelcomeEmail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public function build()
{
sleep(10);
throw new \Exception("TEST JOB FAILED!");
}
}
I am running Horizion successfully using a Supervisor configuration as described here: https://laravel.com/docs/5.6/horizon#deploying-horizon
[program:horizon]
process_name=%(program_name)s
command=php /home/ubuntu/code/myapp/artisan horizon
autostart=true
autorestart=true
user=vagrant
redirect_stderr=true
stdout_logfile=/home/ubuntu/code/myapp/storage/horizon.log
When running the above mailable like so:
new WelcomeMail();
a new job is created and fails after about 10 seconds as expected.
My issue is that Horizon doesn't seem to retry jobs that failed. By default it should be retrying after 90 seconds (according to config/queue.php), for 3 times (according to config/horizon.php).
So why are my failed jobs not retrying?
Related
I am trying to set up my queue worker in Laravel 5.3 and am trying to ensure that I fully understand nuances of the interrelated parameters expire, --tries, --timeout, because the results I am seeing suggest I am not understanding something.
Note: In the Laravel 5.3 documentation (https://laravel.com/docs/5.3/queues#introduction), it refers to retry_after as being a parameter for the database queue connection type, but in my installation of Laravel 5.3, that parameter seems to be expire.
In any case, I have a job, let's call it SendReminder. I purposefully added a line of code that causes an error, so I can test the functioning of the queue tries/retries and eventual labeling of the job as failed in the failed_jobs table.
Here is my database queue config in queue.php:
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 7,
'expire' => 7,
],
For testing, I want to let it try 3 times before being sent to failed_jobs table.
I expect the job to take not more than 5 seconds, and so setting --timeout=5, and expire to 7 (or retry_after to 7), would seem to be in line with the Queue documentation, which says "The --timeout value should always be at least several seconds shorter than your retry_after configuration value. This will ensure that a worker processing a given job is always killed before the job is retried."
Based on above, I expect the job to be considered failed after 21 seconds.
After running php artisan queue:work --daemon --queue=email,default --timeout=5 --tries=3 and then dispatching the job via php artisan schedule:run >> /dev/null 2>&1
I count with my stopwatch 9 seconds until the queue worker displays
[2021-09-02 14:22:14] Failed: App\Jobs\PrepareSendReminderJob
and in my Laravel log I see
[2021-09-02 14:22:08] local.ERROR: ErrorException:
[2021-09-02 14:22:11] local.ERROR: ErrorException:
[2021-09-02 14:22:14] local.ERROR: ErrorException:
This doesn't seem to make sense. I would expect, based on my expire being set to 7, that the failure message would only come 21 seconds after the job is dispatched and immediately picked up by the queue. And I get same result every time - 3 seconds between each error message in the log.
Can someone explain why I am seeing this result?
Thanks!
-- Edit:
And here is the job class:
<?php
namespace App\Jobs;
use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;
class SendReminderJob extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
//public function __construct(\App\Services\SearchService $searchService)
public function __construct()
{
$this->queue = 'email';
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
// nothing here for now, except for this line to cause an error on purpose
Log::infoo('text');
}
}
I've been implemented stripe webhook in laravel 7 using library https://github.com/spatie/laravel-stripe-webhooks
The goal is to subscribe my users to plan created in stripe and generate an invoice on charge succeeded webhook request. Now to achieve this I created a cron script that dispatches the job to subscribe users. Also, set up a webhook endpoint in stripe. All setup is done and configuration in environment variables. It works perfectly when set the queue connection to "sync". However, when setting the queue connection to Redis it doesn't work.
Here's the code inside my config/stripe-webhooks.php
<?php
return [
/*
* Stripe will sign each webhook using a secret. You can find the used secret at the
* webhook configuration settings: https://dashboard.stripe.com/account/webhooks.
*/
'signing_secret' => env('STRIPE_WEBHOOK_SECRET'),
/*
* You can define the job that should be run when a certain webhook hits your application
* here. The key is the name of the Stripe event type with the `.` replaced by a `_`.
*
* You can find a list of Stripe webhook types here:
* https://stripe.com/docs/api#event_types.
*/
'jobs' => [
'charge_succeeded' => \App\Jobs\StripeWebhooks\ChargeSucceededJob::class,
// 'source_chargeable' => \App\Jobs\StripeWebhooks\HandleChargeableSource::class,
// 'charge_failed' => \App\Jobs\StripeWebhooks\HandleFailedCharge::class,
],
/*
* The classname of the model to be used. The class should equal or extend
* Spatie\StripeWebhooks\ProcessStripeWebhookJob.
*/
'model' => \Spatie\StripeWebhooks\ProcessStripeWebhookJob::class,
];
And inside the command that dispatches SubscribeCustomerJob:
$subscribed = 0;
$users = User::role('admin')->where(function ($q) {
$q->where('stripe_id', '!=', null)->where('verified_employees', '>=', 5);
})->get();
foreach ($users as $user) {
if ( $user->subscribed('default') && now()->format('Y-m-d') >= $user->trial_ends_at->format('Y-m-d')) {
SubscribeCustomerJob::dispatch($user)->onQueue('api');
$subscribed++;
}
}
Handling webhook requests using jobs
<?php
namespace App\Jobs\StripeWebhooks;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Spatie\WebhookClient\Models\WebhookCall;
class HandleChargeableSource implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
/** #var \Spatie\WebhookClient\Models\WebhookCall */
public $webhookCall;
public function __construct(WebhookCall $webhookCall)
{
$this->webhookCall = $webhookCall;
}
public function handle()
{
// At this point, I store data to Payments table,
// generate invoice and send email notification to subscribed user.
}
}
The output inside the logs of job:
[2021-04-14 07:53:46][Nr84GbvR3kxqnBGRrrWHtkTj34XRYsGv] Processing: App\Jobs\SubscribeCustomerJob
[2021-04-14 07:53:53][Nr84GbvR3kxqnBGRrrWHtkTj34XRYsGv] Processed: App\Jobs\SubscribeCustomerJob
Inside table in webhook_calls:
webhook_calls table click to see it
All thigs works well with queue connection set to sync. However, the problem is when I set queue connection to "redis".
I know webhook call works because there's data inside webhook_calls table but I guess fails to reach the job.
Any idea with stripe webhook and laravel using redis as queue driver, please add your comment below and thanks in advance.
I've fixed this issue it's my bad that I accidentally put an invalid queue name in my queue worker setup in supervisor.
[program:queue-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work --queue=api,notification
autostart=true
autorestart=true
user=root
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/html/worker.log
I have a job in Laravel 5.5 that doesn't respect the value in the variable public $timeout set on the job as described in the laravel documentation.
If I set the value of $timeout to, for example, 120 seconds I would expect the job to be terminated after it has ran for 120 seconds. I'm using RabbitMQ on a Heroku dyno.
Codebase:
Laravel 5.5
Extension:
RabbitMQ Queue driver for Laravel
Platform:
Heroku dyno (Amazon).
Example code:
class ExampleJob implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 120;
public function handle()
{
DB::statement($this->buildCallStatement());
}
}
Example Procfile:
worker: php artisan queue:listen rabbitmq --queue=high,medium,low --tries=1 --memory=512 --timeout=0
On your example command you are setting a timeout of 0 which is likely overriding your member variable. Also, setting a timeout of 0 can be dangerous and may cause an infinite loop.
I have a Laravel project with a queue, running ~1000 jobs a day.
When a job is failing, in 5.7, it was moved to failed_jobs table, and I was able to retry it.
After migration to Laravel 5.8, jobs just disappear.
This code should mark a job as failed and put it in the failed-jobs table.
/**
* Execute the job.
*/
public function handle()
{
throw new \Exception('WRONG JOB');
}
Supervisor log in that case:
[2019-04-10 15:07:57][11932] Processing: App\Jobs\ExecuteAction
It seems that execution stops, and Queue::failing event is not called.
This code works, but doesn't seem right to me.
class ExecuteAction implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Execute the job.
*/
public function handle()
{
try {
throw new \Exception('WROOONG');
} catch (\Exception $e) {
if ($this->attempts() < $this->tries) {
$this->release(10);
} else {
$this->fail($e);
}
}
}
}
Queue::failing event is called.
Supervisor log ;
[2019-04-10 15:06:52][11926] Processing: App\Jobs\ExecuteAction
[2019-04-10 15:06:52][11926] Failed: App\Jobs\ExecuteAction
[2019-04-10 15:06:52][11926] Processed: App\Jobs\ExecuteAction
In supervisor conf
command=php /path/to/laravel-project/artisan queue:listen
What I am doing wrong ?
Thank you for your help.
From: https://laravel.com/docs/5.8/queues
The command: queue:listen was removed from the documentation and now the recommended way to work with queues is to run: queue:work.
See: https://laravel.com/docs/5.8/queues#running-the-queue-worker
Or you may use: Laravel Horizon
I have 2 laravel (5.2) apps sharing the same database. The 2 apps are used by 2 different user types. Now I want to get them connected to each other so that when a request is sent from a user using the first app to save data to specific database table, a notification is sent to the second app with this data. How can I do this ??
I did the following in the past:
Create a Queue-able job in APP1 with an empty handler.
Trigger a queued job in APP1
Create a Queue-able job in APP2 with a filled out handler.
Work the Queue in APP2 (php artisan queue:listen for example)
Then queue the job in APP1. For example:
# APP1 - trigger
\Queue::push(new \App\Jobs\EventToBeWorkedOnInApp1());
# app1/Jobs/EventToBeWorkedOnInApp1.php - job
class EventToBeWorkedOnInApp1 extends Job implements SelfHandling, ShouldQueue
{
use SerializesModels;
public function handle()
{
// #handler is in APP2
}
(...)
And in APP2 Create the handler for the job
# APP2
# app1/Jobs/EventToBeWorkedOnInApp1.php - job
class EventToBeWorkedOnInApp1 extends Job implements SelfHandling, ShouldQueue
{
use SerializesModels;
public function handle()
{
// WORK WITH THE JOB
}
(...)