Nexus / app /services /batch_api.py
abc1181's picture
REBUILD
aca03d2
Raw
History Blame Contribute Delete
3.02 kB
from __future__ import annotations
import asyncio, json, uuid, time
from sqlalchemy import select
from app.models.batch_job import BatchJob
from app.services.storage import async_session_maker
from app.services.connection_pool import get_client
MAX_BATCH_SIZE = 50
MAX_CONCURRENT = 5
async def create_batch(session, requests: list, model: str) -> dict:
if len(requests) > MAX_BATCH_SIZE:
requests = requests[:MAX_BATCH_SIZE]
batch_id = str(uuid.uuid4())
total = len(requests)
results = []
completed = 0
failed = 0
session.add(BatchJob(
id=batch_id, status="processing", total=total,
completed=0, failed=0, results="[]",
))
await session.commit()
semaphore = asyncio.Semaphore(MAX_CONCURRENT)
client = get_client()
async def _process(req: dict, idx: int):
nonlocal completed, failed
async with semaphore:
try:
url = req.get("url", "")
method = req.get("method", "POST").upper()
headers = req.get("headers", {})
body = req.get("body", {})
if method == "GET":
resp = await client.get(url, headers=headers, timeout=120.0)
else:
resp = await client.post(url, headers=headers, json=body, timeout=120.0)
result = {
"index": idx, "status_code": resp.status_code,
"body": resp.text[:10000],
"error": "",
}
results.append(result)
if resp.is_success:
completed += 1
else:
failed += 1
except Exception as e:
results.append({"index": idx, "status_code": 0, "body": "", "error": str(e)})
failed += 1
tasks = [_process(req, i) for i, req in enumerate(requests)]
await asyncio.gather(*tasks)
status = "completed" if failed == 0 else ("partial" if completed > 0 else "failed")
await session.execute(
select(BatchJob).where(BatchJob.id == batch_id)
)
row = (await session.execute(select(BatchJob).where(BatchJob.id == batch_id))).scalar_one()
row.status = status
row.completed = completed
row.failed = failed
row.results = json.dumps(results)
row.completed_at = time.time()
await session.commit()
return {
"batch_id": batch_id,
"status": status,
"total": total,
"completed": completed,
"failed": failed,
}
async def get_batch_history(session) -> list:
result = await session.execute(
select(BatchJob).order_by(BatchJob.created_at.desc()).limit(50)
)
rows = result.scalars().all()
return [
{
"batch_id": r.id, "status": r.status,
"total": r.total, "completed": r.completed, "failed": r.failed,
"created_at": r.created_at, "completed_at": r.completed_at,
}
for r in rows
]