Bound ?limit and ?offset on /jobs and /dlq
This commit is contained in:
parent
761956eb70
commit
3c608046e2
3 changed files with 20 additions and 6 deletions
|
|
@ -1,4 +1,4 @@
|
|||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
|
||||
from haiku.rag.ingester.api.server import APIState, get_state
|
||||
from haiku.rag.ingester.queue.models import Job, JobStatus
|
||||
|
|
@ -9,8 +9,8 @@ router = APIRouter(prefix="/dlq", tags=["dlq"])
|
|||
@router.get("", response_model=list[Job])
|
||||
async def list_dlq(
|
||||
source_id: str | None = None,
|
||||
limit: int = 50,
|
||||
offset: int = 0,
|
||||
limit: int = Query(50, ge=1, le=500),
|
||||
offset: int = Query(0, ge=0),
|
||||
state: APIState = Depends(get_state),
|
||||
) -> list[Job]:
|
||||
"""Jobs that exhausted retries or hit a permanent error."""
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
|
||||
from haiku.rag.ingester.api.schemas import CancelResponse
|
||||
from haiku.rag.ingester.api.server import APIState, get_state
|
||||
|
|
@ -12,8 +12,8 @@ async def list_jobs(
|
|||
status: JobStatus | None = None,
|
||||
source_id: str | None = None,
|
||||
uri: str | None = None,
|
||||
limit: int = 50,
|
||||
offset: int = 0,
|
||||
limit: int = Query(50, ge=1, le=500),
|
||||
offset: int = Query(0, ge=0),
|
||||
state: APIState = Depends(get_state),
|
||||
) -> list[Job]:
|
||||
return await state.job_repo.list_jobs(
|
||||
|
|
|
|||
|
|
@ -195,6 +195,20 @@ async def test_list_jobs_returns_recent_first(state, jobs):
|
|||
assert [j["id"] for j in payload] == [j2.id, j1.id]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_jobs_rejects_out_of_range_limit_and_offset(state):
|
||||
"""Limit is capped at 500 and >=1; offset is >=0. Without bounds a
|
||||
malicious or careless ?limit=10000000 would block the event loop on
|
||||
serialization."""
|
||||
async with _client(state) as client:
|
||||
for q in ("/jobs?limit=0", "/jobs?limit=501", "/jobs?offset=-1"):
|
||||
resp = await client.get(q)
|
||||
assert resp.status_code == 422, q
|
||||
for q in ("/dlq?limit=0", "/dlq?limit=501", "/dlq?offset=-1"):
|
||||
resp = await client.get(q)
|
||||
assert resp.status_code == 422, q
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_jobs_filters_by_source_and_status(state, jobs):
|
||||
# Enqueue b first so claim_next reaches it before the a row.
|
||||
|
|
|
|||
Loading…
Reference in a new issue