11import json
22from apscheduler .events import EVENT_ALL
3+ from apscheduler .executors .asyncio import AsyncIOExecutor
34from apscheduler .executors .pool import ThreadPoolExecutor , ProcessPoolExecutor
4- from apscheduler .schedulers .background import BackgroundScheduler
55from apscheduler .jobstores .memory import MemoryJobStore
66from apscheduler .jobstores .redis import RedisJobStore
77from apscheduler .jobstores .sqlalchemy import SQLAlchemyJobStore
8+ from apscheduler .schedulers .asyncio import AsyncIOScheduler
9+ from apscheduler .schedulers .background import BackgroundScheduler
810from apscheduler .triggers .cron import CronTrigger
11+ from asyncio import iscoroutinefunction
912from datetime import datetime , timedelta
1013from sqlalchemy .engine import create_engine
1114from sqlalchemy .orm import sessionmaker
@@ -109,9 +112,12 @@ def __find_recent_workday(cls, day: int):
109112 )
110113 ),
111114}
115+ async_executors = {'default' : AsyncIOExecutor ()}
112116executors = {'default' : ThreadPoolExecutor (20 ), 'processpool' : ProcessPoolExecutor (5 )}
113117job_defaults = {'coalesce' : False , 'max_instance' : 1 }
118+ async_scheduler = AsyncIOScheduler ()
114119scheduler = BackgroundScheduler ()
120+ async_scheduler .configure (jobstores = job_stores , executors = async_executors , job_defaults = job_defaults )
115121scheduler .configure (jobstores = job_stores , executors = executors , job_defaults = job_defaults )
116122
117123
@@ -129,14 +135,14 @@ async def init_system_scheduler(cls):
129135 """
130136 logger .info ('开始启动定时任务...' )
131137 scheduler .start ()
138+ async_scheduler .start ()
132139 async with AsyncSessionLocal () as session :
133140 job_list = await JobDao .get_job_list_for_scheduler (session )
134141 for item in job_list :
135- query_job = cls .get_scheduler_job (job_id = str (item .job_id ))
136- if query_job :
137- cls .remove_scheduler_job (job_id = str (item .job_id ))
142+ cls .remove_scheduler_job (job_id = str (item .job_id ))
138143 cls .add_scheduler_job (item )
139144 scheduler .add_listener (cls .scheduler_event_listener , EVENT_ALL )
145+ async_scheduler .add_listener (cls .scheduler_event_listener , EVENT_ALL )
140146 logger .info ('系统初始定时任务加载成功' )
141147
142148 @classmethod
@@ -147,6 +153,7 @@ async def close_system_scheduler(cls):
147153 :return:
148154 """
149155 scheduler .shutdown ()
156+ async_scheduler .shutdown ()
150157 logger .info ('关闭定时任务成功' )
151158
152159 @classmethod
@@ -157,7 +164,7 @@ def get_scheduler_job(cls, job_id: Union[str, int]):
157164 :param job_id: 任务id
158165 :return: 任务对象
159166 """
160- query_job = scheduler .get_job (job_id = str (job_id ))
167+ query_job = scheduler .get_job (job_id = str (job_id )) or async_scheduler . get_job ( job_id = str ( job_id ))
161168
162169 return query_job
163170
@@ -169,8 +176,9 @@ def add_scheduler_job(cls, job_info: JobModel):
169176 :param job_info: 任务对象信息
170177 :return:
171178 """
172- scheduler .add_job (
173- func = eval (job_info .invoke_target ),
179+ job_func = eval (job_info .invoke_target )
180+ job_param = dict (
181+ func = job_func ,
174182 trigger = MyCronTrigger .from_crontab (job_info .cron_expression ),
175183 args = job_info .job_args .split (',' ) if job_info .job_args else None ,
176184 kwargs = json .loads (job_info .job_kwargs ) if job_info .job_kwargs else None ,
@@ -180,8 +188,11 @@ def add_scheduler_job(cls, job_info: JobModel):
180188 coalesce = True if job_info .misfire_policy == '2' else False ,
181189 max_instances = 3 if job_info .concurrent == '0' else 1 ,
182190 jobstore = job_info .job_group ,
183- executor = job_info .job_executor ,
184191 )
192+ if iscoroutinefunction (job_func ):
193+ async_scheduler .add_job (** job_param )
194+ else :
195+ scheduler .add_job (executor = job_info .job_executor , ** job_param )
185196
186197 @classmethod
187198 def execute_scheduler_job_once (cls , job_info : JobModel ):
@@ -191,8 +202,9 @@ def execute_scheduler_job_once(cls, job_info: JobModel):
191202 :param job_info: 任务对象信息
192203 :return:
193204 """
194- scheduler .add_job (
195- func = eval (job_info .invoke_target ),
205+ job_func = eval (job_info .invoke_target )
206+ job_param = dict (
207+ func = job_func ,
196208 trigger = 'date' ,
197209 run_date = datetime .now () + timedelta (seconds = 1 ),
198210 args = job_info .job_args .split (',' ) if job_info .job_args else None ,
@@ -203,8 +215,11 @@ def execute_scheduler_job_once(cls, job_info: JobModel):
203215 coalesce = True if job_info .misfire_policy == '2' else False ,
204216 max_instances = 3 if job_info .concurrent == '0' else 1 ,
205217 jobstore = job_info .job_group ,
206- executor = job_info .job_executor ,
207218 )
219+ if iscoroutinefunction (job_func ):
220+ async_scheduler .add_job (** job_param )
221+ else :
222+ scheduler .add_job (executor = job_info .job_executor , ** job_param )
208223
209224 @classmethod
210225 def remove_scheduler_job (cls , job_id : Union [str , int ]):
@@ -214,7 +229,14 @@ def remove_scheduler_job(cls, job_id: Union[str, int]):
214229 :param job_id: 任务id
215230 :return:
216231 """
217- scheduler .remove_job (job_id = str (job_id ))
232+ query_job = cls .get_scheduler_job (job_id = job_id )
233+ if query_job :
234+ query_job_info = query_job .__getstate__ ()
235+ job_func = eval (query_job_info .get ('func' ).replace (':' , '.' ))
236+ if iscoroutinefunction (job_func ):
237+ async_scheduler .remove_job (job_id = str (job_id ))
238+ else :
239+ scheduler .remove_job (job_id = str (job_id ))
218240
219241 @classmethod
220242 def scheduler_event_listener (cls , event ):
0 commit comments