Laravel version 8.83.17.
I've been using laravel for years and this seems to be a weird problem only occured in one of my mac machine.
Queue driver is using local Redis. have set QUEUE_CONNECTION=redis. And connection is ok.
Then Run php artisan queue:work --queue=test on one of the command window
class TestJob implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct() {}
public function handle() {
Log::debug('TestJobRun');
}
}
Running TestJob::dispatch()->onQueue('test') on tinker to dispatch a simple job TestJob. Nothing happend.
until I run TestJob::dispatchSync(), suddenly the previous job fired together. with the logs 'TestJobRun'
[2023-09-14 19:09:15][a4kFc8yYeVg3agjsFnYP0K5BYbH9NtiD] Processing: App\Jobs\TestJob
[2023-09-14 19:09:15][a4kFc8yYeVg3agjsFnYP0K5BYbH9NtiD] Processed: App\Jobs\TestJob
I just dont know why. how to debug this?
I tried thanging queue, sleep, timeout settings for queue:work. Tried swiching to queue:listen or supervisor ways. Nothing helped.
This is not related to the queue you're trying to use. It is related to trying to dispatch a job from tinker.
The
dispatch()method creates aPendingDispatchobject instance. The job is sent to the queue from the destructor of thePendingDispatchinstance, so the job will not be queued until this instance is destroyed.When running commands in tinker, the result of the last command is kept in memory. Because the result of your last command was the
PendingDispatchinstance, and it is being kept in memory, the destructor is not being called on it, and the job is not dispatching.The next command you run will push the
PendingDispatchinstance out of memory, call the destructor, and your job will be sent to the queue.This is why your second call to
TestJob::dispatchSync()dispatched two jobs. The first one was the one from thePendingDispatchinstance finally being destroyed, and the second one was the one from the call toTestJob::dispatchSync()(which does not use aPendingDispatchinstance).In tinker, instead of using the
::dispatch()method on the job, you can use theBus::dispatch()method directly.Or, you can append another command to your dispatch command so that the result of your command isn't the
PendingDispatchinstance. Ex:Now the result of your command will be the result of the appended
echo;instead of thePendingDispatchinstance returned from thedistpatch(). Therefore, thePendingDispatchinstance will immediately be destroyed and your job will dispatch.NB: this is also noted in the Laravel documentation: