@@ -109,6 +109,44 @@ def _get_job_sync(self, job_id: str) -> dict | None:
109109 async def get_job (self , job_id : str ) -> dict | None :
110110 return await asyncio .get_event_loop ().run_in_executor (None , self ._get_job_sync , job_id )
111111
112+ def _list_recent_jobs_sync (self , limit : int = 20 ) -> list [dict ]:
113+ rows = self ._conn ().execute (
114+ "SELECT id, type, status, input, created_at, updated_at FROM jobs "
115+ "ORDER BY created_at DESC LIMIT ?" ,
116+ (limit ,),
117+ ).fetchall ()
118+ out : list [dict ] = []
119+ for row in rows :
120+ d = dict (row )
121+ d ["input" ] = json .loads (d ["input" ]) if d ["input" ] else {}
122+ out .append (d )
123+ return out
124+
125+ async def list_recent_jobs (self , limit : int = 20 ) -> list [dict ]:
126+ return await asyncio .get_event_loop ().run_in_executor (None , self ._list_recent_jobs_sync , limit )
127+
128+ def _find_latest_single_job_sync (self , username : str , repo : str = "" ) -> dict | None :
129+ rows = self ._conn ().execute (
130+ "SELECT * FROM jobs WHERE type='single' ORDER BY updated_at DESC LIMIT 500"
131+ ).fetchall ()
132+ wanted_user = (username or "" ).strip ().lower ()
133+ wanted_repo = (repo or "" ).strip ()
134+ for row in rows :
135+ d = dict (row )
136+ inp = json .loads (d ["input" ]) if d .get ("input" ) else {}
137+ job_user = (inp .get ("username" ) or "" ).strip ().lower ()
138+ job_repo = (inp .get ("repo" ) or "" ).strip ()
139+ if job_user == wanted_user and job_repo == wanted_repo :
140+ d ["input" ] = inp
141+ d ["result" ] = json .loads (d ["result" ]) if d .get ("result" ) else None
142+ return d
143+ return None
144+
145+ async def find_latest_single_job (self , username : str , repo : str = "" ) -> dict | None :
146+ return await asyncio .get_event_loop ().run_in_executor (
147+ None , self ._find_latest_single_job_sync , username , repo
148+ )
149+
112150 # ── Cache ─────────────────────────────────────────────────────────────────
113151
114152 def _cache_get_sync (self , key : str ) -> Any | None :
0 commit comments