1+ import logging
2+ from typing import Callable , Coroutine , Any
3+
4+ from apscheduler .schedulers .asyncio import AsyncIOScheduler
5+ from apscheduler .triggers .cron import CronTrigger
6+ from apscheduler .triggers .interval import IntervalTrigger
7+
8+ logger = logging .getLogger (__name__ )
9+
10+
11+ class AppScheduler :
12+ def __init__ (self , timezone : str = "Europe/Moscow" ):
13+ self .scheduler = AsyncIOScheduler (
14+ timezone = timezone ,
15+ job_defaults = {
16+ "coalesce" : True ,
17+ "max_instances" : 2 ,
18+ "misfire_grace_time" : 300 ,
19+ },
20+ )
21+
22+ def add_cron_job (
23+ self ,
24+ func : Callable [..., Coroutine [Any , Any , None ]],
25+ * ,
26+ id : str ,
27+ name : str | None = None ,
28+ hour : int | str = "*" ,
29+ minute : int | str = "*" ,
30+ day_of_week : str = "*" ,
31+ args : tuple | None = None ,
32+ kwargs : dict | None = None ,
33+ ) -> None :
34+ self .scheduler .add_job (
35+ func ,
36+ trigger = CronTrigger (
37+ hour = hour ,
38+ minute = minute ,
39+ day_of_week = day_of_week ,
40+ ),
41+ id = id ,
42+ name = name or id ,
43+ args = args or (),
44+ kwargs = kwargs or {},
45+ )
46+ logger .info ("Registered cron job: %s (%s:%s)" , id , hour , minute )
47+
48+ def add_interval_job (
49+ self ,
50+ func : Callable [..., Coroutine [Any , Any , None ]],
51+ * ,
52+ id : str ,
53+ name : str | None = None ,
54+ minutes : int = 1 ,
55+ args : tuple | None = None ,
56+ kwargs : dict | None = None ,
57+ ) -> None :
58+ self .scheduler .add_job (
59+ func ,
60+ trigger = IntervalTrigger (minutes = minutes ),
61+ id = id ,
62+ name = name or id ,
63+ args = args or (),
64+ kwargs = kwargs or {},
65+ )
66+ logger .info ("Registered interval job: %s (every %d min)" , id , minutes )
67+
68+ async def start (self ) -> None :
69+ self .scheduler .start ()
70+ logger .info (
71+ "Scheduler started with %d jobs" , len (self .scheduler .get_jobs ())
72+ )
73+
74+ async def shutdown (self ) -> None :
75+ if self .scheduler .running :
76+ self .scheduler .shutdown (wait = True )
77+ logger .info ("Scheduler stopped gracefully" )
0 commit comments