@@ -45,7 +45,10 @@ class AutomationRun(Base):
4545 error = Column (Text , nullable = True )
4646 created_at = Column (BigInteger , nullable = False )
4747
48- __table_args__ = (Index ('ix_automation_run_automation_id' , 'automation_id' ),)
48+ __table_args__ = (
49+ Index ('ix_automation_run_automation_id' , 'automation_id' ),
50+ Index ('ix_automation_run_aid_created' , 'automation_id' , 'created_at' ),
51+ )
4952
5053
5154####################
@@ -308,6 +311,37 @@ def get_latest(self, automation_id: str, db: Optional[Session] = None) -> Option
308311 )
309312 return AutomationRunModel .model_validate (row ) if row else None
310313
314+ def get_latest_batch (
315+ self , automation_ids : list [str ], db : Optional [Session ] = None
316+ ) -> dict [str , AutomationRunModel ]:
317+ """Fetch the latest run for each automation in a single query."""
318+ if not automation_ids :
319+ return {}
320+ with get_db_context (db ) as db :
321+ # Subquery: max created_at per automation_id
322+ subq = (
323+ db .query (
324+ AutomationRun .automation_id ,
325+ func .max (AutomationRun .created_at ).label ('max_created' ),
326+ )
327+ .filter (AutomationRun .automation_id .in_ (automation_ids ))
328+ .group_by (AutomationRun .automation_id )
329+ .subquery ()
330+ )
331+ rows = (
332+ db .query (AutomationRun )
333+ .join (
334+ subq ,
335+ (AutomationRun .automation_id == subq .c .automation_id )
336+ & (AutomationRun .created_at == subq .c .max_created ),
337+ )
338+ .all ()
339+ )
340+ return {
341+ row .automation_id : AutomationRunModel .model_validate (row )
342+ for row in rows
343+ }
344+
311345 def get_by_automation (
312346 self ,
313347 automation_id : str ,
0 commit comments