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

客户希望建个自动报告发送表 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 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
最佳答案

写一个监听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年前

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