1- import uuid
21from logging import getLogger
32
43from aiopg import Pool , create_pool
5- from pydantic import ValidationError
64from taskiq import ScheduledTask
75
86from taskiq_pg import exceptions
97from taskiq_pg ._internal import BasePostgresScheduleSource
108from taskiq_pg .aiopg .queries import (
119 CREATE_SCHEDULES_TABLE_QUERY ,
1210 DELETE_ALL_SCHEDULES_QUERY ,
11+ DELETE_SCHEDULE_QUERY ,
1312 INSERT_SCHEDULE_QUERY ,
1413 SELECT_SCHEDULES_QUERY ,
1514)
@@ -39,42 +38,6 @@ async def _update_schedules_on_startup(self, schedules: list[ScheduledTask]) ->
3938 ],
4039 )
4140
42- def _get_schedules_from_broker_tasks (self ) -> list [ScheduledTask ]:
43- """Extract schedules from the broker's registered tasks."""
44- scheduled_tasks_for_creation : list [ScheduledTask ] = []
45- for task_name , task in self ._broker .get_all_tasks ().items ():
46- if "schedule" not in task .labels :
47- logger .debug ("Task %s has no schedule, skipping" , task_name )
48- continue
49- if not isinstance (task .labels ["schedule" ], list ):
50- logger .warning (
51- "Schedule for task %s is not a list, skipping" ,
52- task_name ,
53- )
54- continue
55- for schedule in task .labels ["schedule" ]:
56- try :
57- new_schedule = ScheduledTask .model_validate (
58- {
59- "task_name" : task_name ,
60- "labels" : schedule .get ("labels" , {}),
61- "args" : schedule .get ("args" , []),
62- "kwargs" : schedule .get ("kwargs" , {}),
63- "schedule_id" : str (uuid .uuid4 ()),
64- "cron" : schedule .get ("cron" , None ),
65- "cron_offset" : schedule .get ("cron_offset" , None ),
66- "time" : schedule .get ("time" , None ),
67- },
68- )
69- scheduled_tasks_for_creation .append (new_schedule )
70- except ValidationError :
71- logger .exception (
72- "Schedule for task %s is not valid, skipping" ,
73- task_name ,
74- )
75- continue
76- return scheduled_tasks_for_creation
77-
7841 async def startup (self ) -> None :
7942 """
8043 Initialize the schedule source.
@@ -89,7 +52,7 @@ async def startup(self) -> None:
8952 )
9053 async with self ._database_pool .acquire () as connection , connection .cursor () as cursor :
9154 await cursor .execute (CREATE_SCHEDULES_TABLE_QUERY .format (self ._table_name ))
92- scheduled_tasks_for_creation = self ._get_schedules_from_broker_tasks ()
55+ scheduled_tasks_for_creation = self .extract_scheduled_tasks_from_broker ()
9356 await self ._update_schedules_on_startup (scheduled_tasks_for_creation )
9457 except Exception as error :
9558 raise exceptions .DatabaseConnectionError (str (error )) from error
@@ -122,3 +85,42 @@ async def get_schedules(self) -> list["ScheduledTask"]:
12285 ),
12386 )
12487 return schedules
88+
89+ async def add_schedule (self , schedule : "ScheduledTask" ) -> None :
90+ """
91+ Add a new schedule.
92+
93+ Args:
94+ schedule: schedule to add.
95+ """
96+ async with self ._database_pool .acquire () as connection , connection .cursor () as cursor :
97+ await cursor .execute (
98+ INSERT_SCHEDULE_QUERY .format (self ._table_name ),
99+ [
100+ schedule .schedule_id ,
101+ schedule .task_name ,
102+ schedule .model_dump_json (
103+ exclude = {"schedule_id" , "task_name" },
104+ ),
105+ ],
106+ )
107+
108+ async def delete_schedule (self , schedule_id : str ) -> None :
109+ """
110+ Method to delete schedule by id.
111+
112+ This is useful for schedule cancelation.
113+
114+ Args:
115+ schedule_id: id of schedule to delete.
116+ """
117+ async with self ._database_pool .acquire () as connection , connection .cursor () as cursor :
118+ await cursor .execute (
119+ DELETE_SCHEDULE_QUERY .format (self ._table_name ),
120+ [schedule_id ],
121+ )
122+
123+ async def post_send (self , task : ScheduledTask ) -> None :
124+ """Delete a task after it's completed."""
125+ if task .time is not None :
126+ await self .delete_schedule (task .schedule_id )
0 commit comments