11import asyncio
2+ import croniter
3+
4+ from datetime import datetime , timedelta
5+ from beanie .operators import In
6+ from json_schema_to_pydantic import create_model
27
38from app .models .db .graph_template_model import GraphTemplate
49from app .models .graph_template_validation_status import GraphTemplateValidationStatus
510from app .models .db .registered_node import RegisteredNode
611from app .singletons .logs_manager import LogsManager
7- from json_schema_to_pydantic import create_model
12+ from app .models .trigger_models import Trigger , CronTrigger , TriggerStatusEnum , TriggerTypeEnum
13+ from app .models .db .trigger import Triggers as DatabaseTriggers
14+ from config .settings import get_settings
815
916logger = LogsManager ().get_logger ()
1017
@@ -95,7 +102,54 @@ async def verify_inputs(graph_template: GraphTemplate, registered_nodes: list[Re
95102
96103 return errors
97104
98- async def verify_graph (graph_template : GraphTemplate ):
105+ async def cancel_crons (graph_template : GraphTemplate , old_triggers : list [Trigger ]):
106+ old_crons = set ([CronTrigger (** trigger .value ) for trigger in old_triggers if trigger .type == TriggerTypeEnum .CRON ])
107+ new_crons = set ([CronTrigger (** trigger .value ) for trigger in graph_template .triggers if trigger .type == TriggerTypeEnum .CRON ])
108+
109+ removed = old_crons - new_crons
110+
111+ await DatabaseTriggers .find (
112+ DatabaseTriggers .graph_name == graph_template .name ,
113+ DatabaseTriggers .trigger_status == TriggerStatusEnum .PENDING ,
114+ DatabaseTriggers .type == TriggerTypeEnum .CRON ,
115+ In (DatabaseTriggers .expression , [cron .expression for cron in removed ])
116+ ).update (
117+ {
118+ "$set" : {
119+ "trigger_status" : TriggerStatusEnum .CANCELLED
120+ }
121+ }
122+ ) # type: ignore
123+
124+ async def create_crons (graph_template : GraphTemplate , old_triggers : list [Trigger ]):
125+ old_crons = set ([CronTrigger (** trigger .value ) for trigger in old_triggers if trigger .type == TriggerTypeEnum .CRON ])
126+ new_crons = set ([CronTrigger (** trigger .value ) for trigger in graph_template .triggers if trigger .type == TriggerTypeEnum .CRON ])
127+
128+ crons_to_create = new_crons - old_crons
129+
130+ trigger_ahead_time = get_settings ().trigger_ahead_time
131+ current_time = datetime .now ()
132+ limit_time = datetime .now () + timedelta (minutes = trigger_ahead_time )
133+
134+ new_db_triggers = []
135+ for cron in crons_to_create :
136+ iter = croniter .croniter (cron .expression , current_time )
137+ next_trigger_time = iter .get_next (datetime )
138+
139+ while (next_trigger_time < limit_time ):
140+ new_db_triggers .append (
141+ DatabaseTriggers (
142+ type = TriggerTypeEnum .CRON ,
143+ expression = cron .expression ,
144+ graph_name = graph_template .name ,
145+ trigger_status = TriggerStatusEnum .PENDING ,
146+ trigger_time = next_trigger_time
147+ )
148+ )
149+ next_trigger_time = iter .get_next (datetime )
150+ await DatabaseTriggers .insert_many (new_db_triggers )
151+
152+ async def verify_graph (graph_template : GraphTemplate , old_triggers : list [Trigger ]):
99153 try :
100154 errors = []
101155 registered_nodes = await RegisteredNode .list_nodes_by_templates (graph_template .nodes )
@@ -118,6 +172,9 @@ async def verify_graph(graph_template: GraphTemplate):
118172
119173 graph_template .validation_status = GraphTemplateValidationStatus .VALID
120174 graph_template .validation_errors = []
175+
176+ await asyncio .gather (* [cancel_crons (graph_template , old_triggers ), create_crons (graph_template , old_triggers )])
177+
121178 await graph_template .save ()
122179
123180 except Exception as e :
0 commit comments