在我的应用程序上,用户有他们可以发送的电子邮件列表。他们的帐户有他们希望自动发送电子邮件的时间和他们所在的时区的设置。
由于每个用户的发送时间可能会有很大差异,我想测试一下队列何时被触发的某些场景。
我想在全球范围内用碳设定一个假时间。
在public/index.php
中,我尝试设置:
$time = Carbon::create('2020-09-16 00:00:00');
Carbon::setTestNow($time);
但我的应用程序的各个部分不受影响。
有没有一种全球性的方法来设置假时间?
下面的原始问题:
在我的应用程序上,用户有他们可以发送的电子邮件列表。他们的帐户有他们希望自动发送电子邮件的时间和他们所在的时区的设置。
我有一个命令,它将触发一个发送电子邮件的事件。
在侦听器内部,handle
方法看起来像:
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));
}
请注意,我用Carbon伪造时间,并将其设置为午夜。在本例中,电子邮件应在上午9点发送。记录的信息如下:
local.INFO: email sending at 2020-09-15 09:00:00 and current time is 2020-09-15 00:00:00
所以目前的时间是上午12点,我正在排队等待上午9点发送。
一旦我运行php artisan queue:work
,挂起的作业(电子邮件(就会立即运行并发送。为什么会发生这种情况?他们应该一直排队到上午9点。
也许排队是在使用系统时间,而不在乎我在Carbon中设置了什么?我该如何解决此问题?
编辑:我忘了提到我正在使用Redis
检查您在.env
文件中使用的队列驱动程序。QUEUE_CONNECTION=sync
不允许任何延迟(sync代表同步(。
解决此问题的最快方法是执行以下操作:
- 将驱动程序更改为数据库
QUEUE_CONNECTION=database
- 清除缓存的配置
php artisan config:clear
- 发布作业表
php artisan queue:table
的迁移 - 迁移此新表
php artisan migrate
完成这些步骤后,当您使用php artisan queue:work
运行它时,您现在可以在队列中延迟执行
我认为您应该为此目的使用Laravel Cron Job。您应该在App/Console/Commands/YourRonJobFile.php 中创建一个文件
<?php
namespace AppConsoleCommands;
use AppTestingCron;
use IlluminateConsoleCommand;
use IlluminateSupportFacadesDB;
class TestingCronJob extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'send:Mail';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command is use for test cron jobs.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
DB::table('testing_cron')->insert(['created_at' => now(),'updated_at' => now()]);
}
}
然后转到App/Console/Kernel.php 目录
<?php
namespace AppConsole;
use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
CommandsTestingCronJob::class
];
/**
* Define the application's command schedule.
*
* @param IlluminateConsoleSchedulingSchedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('send:Mail')->dailyAt('09:00');
}
/**
* RegisterController the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
https://laravel.com/docs/7.x/scheduling