MySQL-同步或刷历史数据专题-判断一个周期内不要重复重复执行任务-到期前30天提醒-开始前10分钟提醒
判断一个周期内不要重复重复执行,增加一个最后一次处理时间字段。
示例一:上次处理时间不再当前季度范围内,才要去处理
来自lap劳保榆林化学定制开发
condition.add(String.format("((last_handle_time not between '%s' and '%s') or (last_handle_time is null) or (last_handle_time = ''))",
dto.getCurrentQuarterStart(),
dto.getCurrentQuarterEnd()));
业务处理完了再去更新下last_handle_time
示例二:到期前30天提醒
来自lap劳保榆林化学定制开发
if (dto.getQueryEndDay() != null) {
//必要条件
String where0 = " (daoqishijian is not null and daoqishijian != '') ";
//情况一:正好等于30天的,且当天不要重复 ( 测试还有30天到期的日期 select DATE_FORMAT(DATE_ADD(now(),INTERVAL 30 DAY),'%Y-%m-%d') ==> 2022-12-17 )
String where1 = " ( DATE_FORMAT(now(),'%Y-%m-%d') = DATE_FORMAT(DATE_SUB(daoqishijian,INTERVAL " + dto.getQueryEndDay() + " DAY),'%Y-%m-%d') " +
" and (lastSendExpireDate is null or lastSendExpireDate = '' or DATE_FORMAT(now(),'%Y-%m-%d') != DATE_FORMAT(lastSendExpireDate,'%Y-%m-%d'))) ";
//情况二:(lastSendExpireDate为空或lastSendExpireDate超过30天的(now - 30 > lastSendExpireDate)),且到期时间已经在30天内(now - daoqishijian < 30)的数据需要扫描出来
//分析:
// 今天 11月17号 11月20号到期 ,30天以内的范围 应该是 前开后闭
//now between 10月21号-- 11月20号 已经到期或超过了不管了
//(now > daoqishijian - 30 + 1) and (now < daoqishijian),TODO,这里没有使用 等于号,所以是不是不要+1?
//提醒文案中如果有天数,有的在30天内的会应该小于30
String where2 = " ((lastSendExpireDate is null or lastSendExpireDate = '' or DATE_FORMAT(DATE_SUB(now(),INTERVAL " + dto.getQueryEndDay() + " DAY),'%Y-%m-%d') > DATE_FORMAT(lastSendExpireDate,'%Y-%m-%d')) ";
where2 += " and (DATE_FORMAT(now(),'%Y-%m-%d') > DATE_FORMAT(DATE_SUB(daoqishijian,INTERVAL " + ( dto.getQueryEndDay()) + " DAY),'%Y-%m-%d') and DATE_FORMAT(now(),'%Y-%m-%d') < DATE_FORMAT(daoqishijian,'%Y-%m-%d')))";
condition.add(where0 + " and (" + where1 + " or " + where2 + ") ");
}
示例三:到期前${queryEndDay}天提醒
来自edu中,结合示例二
<select id="getTrainManageExpirationList" resultType="com.safety51.edu.entity.train.EduTrainManager">
select id ,container_id containerId,train_end_time trainEndTime,train_name trainName,creater_id createrId from edu_train_manager
where is_delete = 0
<if test="queryEndDay != null">
and (train_end_time is not null and train_end_time != '')
and ( ( DATE_FORMAT(now(),'%Y-%m-%d') = DATE_FORMAT(DATE_SUB(train_end_time,INTERVAL ${queryEndDay} DAY),'%Y-%m-%d') and (last_send_expire_date is null or last_send_expire_date = '' or DATE_FORMAT(now(),'%Y-%m-%d') != DATE_FORMAT(last_send_expire_date,'%Y-%m-%d')))
or ((last_send_expire_date is null or last_send_expire_date = '' or DATE_FORMAT(DATE_SUB(now(),INTERVAL ${queryEndDay} DAY),'%Y-%m-%d') > DATE_FORMAT(last_send_expire_date,'%Y-%m-%d')) and (DATE_FORMAT(now(),'%Y-%m-%d') > DATE_FORMAT(DATE_SUB(train_end_time,INTERVAL ${queryEndDay} DAY),'%Y-%m-%d') and DATE_FORMAT(now(),'%Y-%m-%d') < DATE_FORMAT(train_end_time,'%Y-%m-%d'))))
</if>
<if test="trainManagerIdList != null and trainManagerIdList.size() > 0">
and last_send_expire_date is null
and id in
<foreach collection="trainManagerIdList" index="index" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</if>
</select>
以上执行时机:
1、程序启动执行一次(会过滤已经处理的数据,30天内没有发送消息的数据会立即发送消息)
2、定时任务每天9点00分(会过滤已经处理的数据)
3、接口调用 /safetyjapi/lpa/withoutLogin/test/sendGoodsExpirationMessage(会过滤已经处理的数据)
4、需要补充一个场景:
//定时任务是上午9点执行,如果是下午创建或修改的数据,并正好是相差7天的,应该相关业务生成后立即执行一次
eduTrainRemindService.sendTrainManageExpirationMessage(Lists.newArrayList(finalId));
示例四:培训开始前10min提醒
定时任务扫描任务开始前10min的任务,注意定时任务默认多线程(可改多线程,但是多线程应该也有资源占用的问题),如果阻塞耗时长,可能导致没扫描到。
/**
* 培训开始前10min提醒
* 每分钟扫描一边 @Scheduled(cron = "0 0/1 * * * ? ")
* 您的【XXX新人入职培训】即将于10min后开始,点击查看详情
*比较死板。只跟实时的时间有关系
*/
@Scheduled(cron = "0 0/1 * * * ? ")
public void eduTrainRemindBeforeStart() {
eduTrainRemindService.eduTrainRemindBeforeStart(null,10);
}
select id,
container_id containerId,
train_name trainName,
train_level trainLevel,
train_start_time trainStartTime,
train_end_time trainEndTime,
pass_standard passStandard,
release_status releaseStatus,
user_intermediate_id userIntermediateId,
train_status trainStatus,
domain,
now() scanTime
from edu_train_implement
where now() > DATE_SUB(DATE_SUB(train_start_time,INTERVAL ${mins} MINUTE),INTERVAL 30 SECOND)
and now() <= DATE_ADD(DATE_SUB(train_start_time,INTERVAL ${mins} MINUTE),INTERVAL 30 SECOND)
<!--未开始,已发布-->
and train_status = 0 and release_status = 1
and is_delete = 0
--------------------------------------------------------------------------------
更多相关逻辑见
《MySQL-同步或刷历史数据专题-根据修改时间-扫描最近3天3小时的数据-最近几天-最近几小时》
《Java-同步或刷历史数据专题-分页刷数据-几种分页模板》