On my application, users have lists of emails they can send to. Their accounts have settings for the time of day they want emails automatically sent and the timezone they’re in.
I would like to test certain scenarios on when my queues are triggered since each user’s send time may differ drastically.
I’d like to globally set a fake time with carbon.
In public/index.php
, I tried to set:
$time = Carbon::create('2020-09-16 00:00:00');
Carbon::setTestNow($time);
but pieces of my application are not affected.
Is there a global way to set a fake time?
Original question below:
On my application, users have lists of emails they can send to. Their accounts have settings for the time of day they want emails automatically sent and the timezone they’re in.
I have a command that will trigger an event that sends email.
Inside the listener, the handle
method looks like:
public function handle(ReviewRequested $event)
{
$time = Carbon::create(2020, 9, 15, 0);
Carbon::setTestNow($time);
$reviewRequest = $event->reviewRequest;
Log::info('email sending at ' . $reviewRequest->sent_at . ' and current time is ' . Carbon::now());
Mail::to($reviewRequest->customer->email)
->later($reviewRequest->sent_at, new ReviewRequestMailer($reviewRequest));
}
Note that I’m faking the time with Carbon and setting it to midnight. In this example, The emails should be sent at 9am. The logged info is as follows:
local.INFO: email sending at 2020-09-15 09:00:00 and current time is 2020-09-15 00:00:00
So the current time is 12AM and I’m queuing these up to get sent at 9AM.
As soon as I run php artisan queue:work
, the pending jobs (emails) are immediately run and sent. Why is this happening? They should remain queued until 9AM.
Perhaps queuing is using system time and doesn’t care about what I set in Carbon? How can I resolve this?
Edit: I forgot to mention that I’m using Redis
2
Answers
Check what queue driver you’re using in your
.env
file.QUEUE_CONNECTION=sync
does not allow for any delaying (sync stands for synchronous).The quickest way to fix this would be doing the following:
QUEUE_CONNECTION=database
php artisan config:clear
php artisan queue:table
php artisan migrate
After following these steps, you can now have delayed execution in your queues when you run it with
php artisan queue:work
I think you should use Laravel Cron Job for this purpose. you should make a file in App/Console/Commands/YourCronJobFile.php
Then go to directory App/Console/Kernel.php
https://laravel.com/docs/7.x/scheduling