I am trying to delay a job in Laravel that is dispatched to a AWS SQS queue. Standard jobs that are not delayed run fine on that queue but as soon as I delay something, it crashes. I first tried:
$awsgatewayjob = new \App\Jobs\DispatchAwsGatewayJob();
$this->dispatch($awsgatewayjob)->delay(now()->addMinutes(1));
This gives error: Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR) Call to a member function delay() on string
Next, I tried to do it using the style Laravel explains in the manual:
DispatchAwsGatewayJob::dispatch()->delay(now()->addMinutes(1));
And this gives error:
Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR) Call to undefined method Maqe\LaravelSqsFifo\SqsFifoQueue::getSeconds()
I googled the last error and I am happy to report I am not the only one that experienced that error: https://github.com/maqe/laravel-sqs-fifo/issues/7
Anyway, I don't get it. I am running on Laravel 5.5 and I updated all my packages with composer update to make sure I wasn't using an outdated package.
Any ideas?
Here is the (redacted) code for the job:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Auth;
use Session;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Alert;
class DispatchAwsGatewayJob implements ShouldQueue
{
private $method;
private $rest_method;
private $data;
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($method, $rest_method, $data)
{
$this->method = $method;
$this->rest_method = $rest_method;
$this->data = $data;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$curl = curl_init();
// some more stuff here to config $curl
$result = curl_exec($curl);
curl_close($curl);
}
}
Here is the full error log:
Symfony\Component\Debug\Exception\FatalThrowableError thrown with message "Call to undefined method Maqe\LaravelSqsFifo\SqsFifoQueue::getSeconds()"
Stacktrace:
This is the complete stacktrace. I am now using a standard queue and everything runs fine!
Your specific error is because the getSeconds()
method was removed in Laravel 5.4. That package has an update in the master branch to add 5.4+ compatibility, but there is no tagged release with that code, so you'd have to update your composer.json file to point to dev-master
.
However, there is a bigger issue at play here. While the package you're using attempts to support the delay
functionality, this isn't actually correct.
SQS FIFO queues do not support per-message delays. They only support per-queue delays, meaning you must define your queue in AWS with a delay (max 15 minutes), as seen in the screenshot below. Attempting to set a delay on a message sent to a queue that is not defined with a delay will not have any effect.
So, if you have some jobs that don't use a delay and some jobs that do use a delay, you would need to create at least two queues: one without a delay defined and one with a delay defined. Then, instead of using the delay()
method, you would have to use the onQueue()
method to send your job to the queue defined with a delay.
Full disclosure: I have also created a Laravel package for handling SQS FIFO queues (shiftonelabs/laravel-sqs-fifo-queue). Because of the per-message delay restriction on FIFO queues, my package throws an exception when the attempt is made (BadMethodCallException('FIFO queues do not support per-message delays.')
), though this behavior can be changed via the package config (as described here).
My package also supports the ability to specify other FIFO specific values, such as the message group id and the deduplication id.