计划任务的执行时间和频率放到数据库中,实现自动化

客户希望建个自动报告发送表 autoSendReport
字段:报告ID,开始日期,结束日期,发送时间,发送频率(1 每天,2每周,3每月),收件人
需求:设置好后,报告就按设置的时间发送到收件人里
举例:2021-4-20到2021-4-30每天10:00发送报告1到收件人xx@qq.com

我的想法,再建立一个发送记录表 sendReportRecord,字段:发送的报告ID,发送状态和发生时间,避免重复发送
我需要设置一个计划任务频率设置到每10分钟检测?
另外一个问题,如果发送频率改变了怎么办

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

写一个监听redis key过期任务 ,每次创建任务、计算第一次发送时间距离现在多久,设置key的过期时间。 每次监听到了,就去数据库查询发送任务、执行发送任务、然后计算下一次发送时间。

2年前 评论
tiansai 2年前
讨论数量: 7

弄个定时任务,频率就是你需求所要的最小频率为单位,比如,你上面要求的最小粒度是每天,那你的定时任务就设置为每天执行一次,然后PHP脚本里面,通过代码判断你客户当前设置的频率,如果是每天,就执行。如果设置的是每周一,那你判断今天试不是周一,是就执行,不是就退出,以此类推

2年前 评论

crontab + 任务调度,每分钟一次,然后通过 SQL 检索条件应该就可以了吧。。

发送记录这个应该有,记录成功失败,发送事件,失败重试等。

2年前 评论

增加一个下次执行时间,频率变化后计算下次执行时间,定时任务频率根据你业务承载自行变化,每次只查询下次执行时间小于当前时间的!

2年前 评论

按照第一性原则,根据生活经验,别人交代你的事情,你是怎么避免忘记的从而执行的?

2年前 评论

写一个监听redis key过期任务 ,每次创建任务、计算第一次发送时间距离现在多久,设置key的过期时间。 每次监听到了,就去数据库查询发送任务、执行发送任务、然后计算下一次发送时间。

2年前 评论
tiansai 2年前

楼上的兄弟们说的都对,我没啥可补充的了。个人觉得一楼的方案就可以了,不用弄的很复杂。

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    protected function schedule(Schedule $schedule)
    {
        // $schedule->command('inspire')->hourly();
        $schedule->call(function(){
           $now = \Carbon\Carbon::now();
           $nowStr = $now->toDateTimeString();
           \App\Models\AutoSendReport::where('开始日期', '<=', $nowStr)
            ->where('结束日期', '>=', $nowStr)
            ->get()
            ->map(function($plan)use($now){
                $shouldSend = false;
                switch ($plan->频率) {
                    case '每天':
                        // 每天上午 10 点发送
                        $shouldSend = true;
                        break;

                    case '每周':
                        // 每周一发送
                        $shouldSend = $now->isMonday();
                        break;

                    case '每月':
                        // 每月第一天发送
                        $shouldSend = $now->day == 1;
                        break;
                }
                if($shouldSend){
                    \Mail::to($plan['收件人邮箱'], $plan['收件人姓名'])->send(new \Illuminate\Mail\Mailable());
                }
            });
        })
        ->timezone('Asia/Shanghai')
        // 每天上午 10 点执行一次
        ->dailyAt('10:00');
    }
}

详细的频率设置参考 文档

2年前 评论
LiamHao (作者) 2年前
xiaohuasheng 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!