Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Laravel:检查是否有新项目添加到db表中,并为电子邮件用户安排作业_Laravel_Laravel Queue_Laravel Scheduler_Laravel Jobs - Fatal编程技术网

Laravel:检查是否有新项目添加到db表中,并为电子邮件用户安排作业

Laravel:检查是否有新项目添加到db表中,并为电子邮件用户安排作业,laravel,laravel-queue,laravel-scheduler,laravel-jobs,Laravel,Laravel Queue,Laravel Scheduler,Laravel Jobs,我想在我的Laravel应用程序中将新行添加到表中时触发电子邮件。然而,我想添加一个排序缓冲区,所以如果快速连续添加5行,那么只发送1封电子邮件 我选择的方法是每15分钟安排一次检查,看看是否添加了新行。如果有,那么我将排队发送电子邮件 目前我在日程安排上有个错误。我将在下面运行我的代码: 在Kernel.php中,我们在其中设置日程安排,我有: $schedule->job(new ProcessActivity) ->everyFifteenMin

我想在我的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和项目模型之间的关系。正如我在代码中所评论的那样,我不会详细说明这一点

问题

当我向JobItem表中添加新行时,我可以看到作业已被调度和处理(使用Laravel望远镜检查)

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

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

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

因此,似乎正在触发onFailure,并且我的ProcessActivity存在问题


如果有任何关于我哪里出错以及如何判断错误的线索,我将不胜感激。

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

我正在使用此artisan命令处理我的计划作业:

php artisan queue:work
在使用该命令时进行开发的问题是,如果有代码更改,则无法识别这些更改

因此,您可以命令+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());
    }
}
首先要注意的是,as _construct()最初运行并序列化。然后在处理作业时调用handle方法。因此,我不得不将我的雄辩的查询转移到handle方法中

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

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

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

不固定100% 有了这段代码,我现在可以在添加新项目时每x分钟自动安排一封电子邮件。但是,我仍然从我的Kernal.php文件的onFailure()中获取日志Fail:

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

我仍然不清楚这意味着什么,我如何才能确定更多关于这一失败的信息以及这意味着什么。但是,它确实有效,因此我将谨慎地向前推进(对评论睁大一只眼,以防有人有什么想法可以帮助!)

我认为您的逻辑中也存在一个问题。你每分钟都在运行时间表。这意味着已经处理的行将在接下来的19分钟内再次处理。@sachinkumar啊!我现在只是为了调试而每分钟都在运行——我会进去修改它,这样它就不会混淆了!你能计算出抛出了什么异常吗?你知道如何@kevin-我如何在onFailure()中转储异常吗?请在你的作业中放置一个try catch并记录异常:try{}catch(\exception$e){\log::info($e->getMessage());}}你启动了调度程序吗?如果调度程序正在运行,那么它也不会反映更改。