1

我想在我的 Laravel 应用程序的表中添加新行时触发一封电子邮件。但是我想添加一个缓冲区,所以如果快速连续添加 5 行,那么只会发送 1 封电子邮件。

我选择的方法是每 15 分钟安排一次检查,看看是否添加了新行。如果有,那么我将排队发送电子邮件。

目前我的日程安排有误。我将在下面运行我的代码:

在我们设置时间表的Kernel.php中,我有:

        $schedule->job(new ProcessActivity)
        ->everyFifteenMinutes()
        ->when(function () {
            return \App\JobItem::whereBetween('created_at', array(Carbon::now()->subMinutes(15), Carbon::now()))->exists();
        })
        ->onSuccess(function () {
            Log::debug(
                'Success'
            );
        })
        ->onFailure(function () {
            Log::debug(
                'Fail'
            );
        });

我用它来触发在App\Jobs\ProcessActivity.php中找到的作业:

 public function __construct()
{

    $this->jobs = \App\JobItem::whereBetween('created_at', array(Carbon::now()->subMinutes(15), Carbon::now()))->get();
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{


    Log::debug('Activity Job Run',  ['jobs' => $this->jobs]);

    $this->jobs->each(function ($item, $key) {
        Log::debug('loop');

        // get project
        $project = $item->project;

        // get project email
        $user_id = $project->user_id;
        $email = \App\User::find($user_id)->email;

        // get project UUID
        $projectUuid = $project->public_id;

        // emails
        $subscriberEmails = \App\ProjectSubscription::where('project_id', $project->id)->get();

        // create activity email
        Notification::route('mail', $subscriberEmails)->notify(new Activity($project, $projectUuid));
    });

    return true;
}

我在上面发布了我的完整代码,其中还显示了我的 JobItems 和 Project 模型之间的关系。正如我在代码中评论的那样,我不会详细说明。

问题

当我在 JobItem 表中添加新行时,我可以看到作业已安排并处理(使用 Laravel Telescope 进行检查)。

但是,我还可以在我的日志中看到,对于每个作业,我都会收到两条日志消息:

首先:“失败”,然后是“活动作业运行

我的电子邮件没有发送,我不确定如何确定失败的原因。

所以似乎 onFailure 被触发了,我的 ProcessActivity 有问题。

任何关于我哪里出错以及如何确定错误的线索将不胜感激。

4

1 回答 1

1

我有一个解决办法,但首先,我学到了一些阻碍我进步的东西:

我正在使用这个工匠命令来处理我的预定作业:

php artisan queue:work

使用该命令进行开发的问题是,如果有代码更改,则无法识别这些更改。

因此,您可以使用 Command+C 返回控制台并在每次代码更改时使用它:

php artisan queue:restart
php artisan queue:work

或者您可以只使用它,它将允许更改代码:

php artisan queue:listen

正如您可以想象的那样,在不知道这一点的情况下,您将有一个缓慢的调试过程!

由于这一点,并为我的工作添加了一个例外,我取得了一些进展。我将粘贴下面的代码以与原始代码进行比较:

    public function __construct()
{
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{
    try {

        $jobs = \App\JobItem::whereBetween('created_at', array(Carbon::now()->subMinutes(20), Carbon::now()))->get();

        Log::debug('Activity Job',  ['jobs' => $jobs]);

        // collection start
        $collection = collect();

        // loop jobs to get emails
        foreach ($jobs as $key => $value) {

            // get project UUID
            $project = $value->project;
            $projectUuid = $project->public_id;

            // get emails subscribed to projects
            $subscriberEmails = \App\ProjectSubscription::where('project_id', $project->id)->get();

            // merge into a single collection via the loop
            if ($key != 0) {
                $merge = $collection->merge($subscriberEmails);
                $collection = collect($merge);
            } else {
                $collection = $subscriberEmails;
            }

            // Log::debug('emails_project in loop', ['emails' => $subscriberEmails]);
        };

        // clean object with uniques only
        $subscriberEmailsCleaned = $collection->unique();

        // debug
        Log::debug('Project Emails to Notify', ['emails' => $subscriberEmailsCleaned]);

        // create activity email
        Notification::route('mail', $subscriberEmailsCleaned)->notify(new Activity($project, $projectUuid));
    } catch (\Exception $e) {
        \Log::info($e->getMessage());
    }
}

首先要注意的是,由于 __construct() 最初运行并被序列化。然后在处理作业时调用handle 方法。所以我不得不把我雄辩的查询移到句柄方法中。

我还使用了一个 foreach 而不是 .each 来循环并创建一个新的电子邮件集合。也许有一种更优雅的方式,但我需要创建一个电子邮件集合,这种方式允许我将循环中的变量移到外部以在方法中使用。

你可以看到我在循环的底部合并了这些。

我还添加了一些对调试有用的 Log:: 项。

未修复 100% 使用此代码,我现在可以在添加新项目时每 x 分钟自动安排一封电子邮件。但是,我仍然从我的 Kernal.php 文件的 onFailure() 中获取日志失败:

        ->onFailure(function () {
        Log::debug(
            'Fail'
        );

我仍然对这表明什么以及如何确定有关它如何失败以及这意味着什么的更多信息感到困惑。但是,它确实有效,所以我会小心翼翼地继续前进(睁大一只眼睛看评论,以防有人有可以提供帮助的想法!)

于 2019-07-17T19:08:44.090 回答