12
12
import sqlalchemy .ext .asyncio
13
13
from sqlalchemy import select , update
14
14
from sqlalchemy .orm import Mapped , mapped_column
15
- from fastapi import FastAPI
15
+ from fastapi import FastAPI , HTTPException
16
16
from aiohttp import ClientSession
17
17
18
18
engine : sqlalchemy .ext .asyncio .AsyncEngine = None
@@ -339,7 +339,7 @@ async def queue_loop(body: QueueRepeatURLBody) -> QueueLoopReturn:
339
339
repeat .active_since = datetime .datetime .now (tz = datetime .timezone .utc )
340
340
return QueueLoopReturn (repeat_id = repeat .id )
341
341
342
- class CurrentJobReturnJob (BaseModel ):
342
+ class JobReturn (BaseModel ):
343
343
id : int
344
344
url : str
345
345
created_at : datetime .datetime
@@ -350,16 +350,9 @@ class CurrentJobReturnJob(BaseModel):
350
350
failed : datetime .datetime | None
351
351
batches : list [int ] = []
352
352
353
- class CurrentJobReturn (BaseModel ):
354
- job : CurrentJobReturnJob | None
355
-
356
- @app .get ("/current_job" )
357
- async def current_job () -> CurrentJobReturn :
358
- job = await get_current_job (get_batches = True )
359
- if job is None :
360
- return {"job" : None }
361
- return {
362
- "job" : CurrentJobReturnJob (
353
+ @classmethod
354
+ def from_job (cls , job : Job ):
355
+ return cls (
363
356
id = job .id ,
364
357
url = job .url .url ,
365
358
created_at = job .created_at ,
@@ -370,4 +363,62 @@ async def current_job() -> CurrentJobReturn:
370
363
failed = job .failed ,
371
364
batches = [batch .id for batch in job .batches ]
372
365
)
373
- }
366
+
367
+ class CurrentJobReturn (BaseModel ):
368
+ job : JobReturn | None
369
+
370
+ @app .get ("/current_job" )
371
+ async def current_job () -> CurrentJobReturn :
372
+ job = await get_current_job (get_batches = True )
373
+ if job is None :
374
+ return {"job" : None }
375
+ return {
376
+ "job" : JobReturn .from_job (job )
377
+ }
378
+
379
+ @app .get ("/job/{job_id}" )
380
+ async def get_job (job_id : int ) -> JobReturn :
381
+ async with async_session () as session , session .begin ():
382
+ stmt = select (Job ).where (Job .id == job_id ).limit (1 )
383
+ job = await session .scalar (stmt )
384
+ if job is None :
385
+ raise HTTPException (status_code = 404 , detail = "Job not found" )
386
+ return JobReturn .from_job (job )
387
+
388
+ class BatchReturn (BaseModel ):
389
+ id : int
390
+ created_at : datetime .datetime
391
+ jobs : list [JobReturn ] = []
392
+
393
+ @app .get ("/batch/{batch_id}" )
394
+ async def get_batch (batch_id : int ):
395
+ async with async_session () as session , session .begin ():
396
+ stmt = select (Batch ).where (Batch .id == batch_id ).limit (1 )
397
+ batch = await session .scalar (stmt )
398
+ if batch is None :
399
+ raise HTTPException (status_code = 404 , detail = "Batch not found" )
400
+ return {
401
+ "id" : batch .id ,
402
+ "created_at" : batch .created_at ,
403
+ "jobs" : [JobReturn .from_job (job ) for job in batch .jobs ]
404
+ }
405
+ class URLInfoBody (BaseModel ):
406
+ url : str
407
+
408
+ class URLReturn (BaseModel ):
409
+ jobs : list [JobReturn ] = []
410
+ first_seen : datetime .datetime
411
+ last_seen : datetime .datetime | None
412
+
413
+ @app .post ("/url" )
414
+ async def get_url_info (body : URLInfoBody ) -> URLReturn :
415
+ async with async_session () as session , session .begin ():
416
+ stmt = select (URL ).where (URL .url == body .url ).limit (1 )
417
+ url = await session .scalar (stmt )
418
+ if url is None :
419
+ raise HTTPException (status_code = 404 , detail = "URL not found" )
420
+ return {
421
+ "jobs" : [JobReturn .from_job (job ) for job in url .jobs ],
422
+ "first_seen" : url .first_seen ,
423
+ "last_seen" : url .last_seen
424
+ }
0 commit comments