async def cal_next_start_time(job, is_normal=True): """ 计算下一次定时任务发生的时间 :param job: :param is_normal :return: """ # 无限循环执行, 必定带正则表达式,否则直接报错 # 解析正则表达式, 计算出下一次需要执行的时间点 if not is_normal: current_time = int(DateUtils.timestamps_now()) else: current_time = DateUtils.str_to_time(job['start_time']) left_time = cron_utils.analyze(current_time + 1, job['cron']) start_time = DateUtils.format_time(current_time + left_time) # 计算距离start_time最近的RUN_TIME秒 current_date = start_time[:16] + ':00' current_count = 1 while current_date < start_time: # 避免死循环 if current_count >= 1000: break current_count += 1 current_date = DateUtils.add_second(current_date, seconds=run_time) start_time = current_date job['start_time'] = start_time cache_key = ServiceBase.schedule.JOB_KEY + job['start_time'].replace( ' ', '').replace('-', '').replace(':', '') now_date = DateUtils.time_now() # 如果下一次的执行时间小于当前时间,则跳至下一个执行的时间节点 if job['start_time'] < now_date: logger.info('任务下一次执行时间小于当前时间') current_date = now_date[:16] + ':00' while current_date < now_date: current_date = DateUtils.add_second(current_date, seconds=2 * run_time) job['start_time'] = current_date cache_key = ServiceBase.schedule.JOB_KEY + job['start_time'].replace( ' ', '').replace('-', '').replace(':', '') model = importlib.import_module('task.schedule.model') model = model.Model() await model.update_job(job) await redis.sadd(cache_key, json.dumps(job, cls=CJsonEncoder)) length = await redis.scard(cache_key) await redis.hset(ServiceBase.schedule.SCHEDULE_KEY, cache_key, length)
async def async_add_job(service_path='', method='', params={}, start_time='', cron='', job_id='', group_name='default', repeat_count=0): """ 添加定时任务 :param service_path: 需要执行的service路径 :param method: 需要执行的方法 :param params: 需要传入的参数 :param start_time: (2018-06-20 16:30:00) :param cron: 这里采用五位表达式,从左到右依次表示秒、分、时、天、月 可以使用具体数字或者区间 20 表示[20] 1-3 表示[1, 2, 3] 1,4,6,7 表示[1, 4, 6, 7] * 表示所有, 1/5 从第1个开始,每五个执行一次 :param job_id: 任务编号,每个任务的编号都要求唯一 :param group_name: :param repeat_count: 如果要求无限次执行, 则该值需要传入-1, 同一个任务有限次多次执行的情况暂不考虑, 如果业务上有需要, 希望你用多个任务来处理这件事 :return: """ if cron: current_time = int(DateUtils.timestamps_now()) left_time = cron_utils.analyze(current_time + 1, cron) start_time = DateUtils.format_time(current_time + left_time) # 计算距离start_time最近的RUN_TIME秒 current_date = start_time[:16] + ':00' current_count = 1 while current_date < start_time: # 避免死循环 if current_count >= 1000: break current_count += 1 current_date = DateUtils.add_second(current_date, seconds=RUN_TIME) start_time = current_date job_params = { 'job_id': job_id, 'group_name': group_name, 'start_time': start_time, 'limit_time': 0, 'repeat_count': repeat_count, 'cron': cron, 'path': service_path, 'method': method, 'params': params } result = await save_job(job_params) return result