اضافه شدن قابلیت share و نگهداری بلندمدت
Verify / test (push) Failing after 22s

This commit is contained in:
2026-11-09 14:55:36 +03:30
والد a4e8f0c6c0
کامیت 19824bd180
27فایلهای تغییر یافته به همراه267 افزوده شده و 51 حذف شده
+8 -8
مشاهده پرونده
@@ -11,7 +11,8 @@ from fastapi.responses import FileResponse, JSONResponse, Response
from sqlalchemy import select, func, text
from starlette.concurrency import run_in_threadpool
from .config import settings
from .db import Job, sessions
from .expiry import expiration
from .db import Job, sessions, active_jobs
from .storage import storage
from .uploads import read_pcb
from .models.pcb import PCBData, PCBStatus, PCBUploadResponse, PCBComparisonStatus, PCBComparisonUploadResponse
@@ -34,18 +35,17 @@ def register_pcb_routes(app, *, authorize, require_api, error):
return result
async def create(files, access, expires_in, comparison):
ttl = expires_in or settings().link_ttl
if ttl > settings().link_ttl: error('invalid_expiry','expires_in exceeds configured link lifetime',422)
now=time.time();expires_at=expiration(expires_in,now)
sources = {}
try:
for field, file in files.items(): sources[field] = await read_pcb(file)
finally:
for file in files.values(): await file.close()
identifier = secrets.token_hex(24); token = secrets.token_urlsafe(32); now = time.time()
identifier = secrets.token_hex(24); token = secrets.token_urlsafe(32)
input_name = 'pcb-comparison.json' if comparison else 'input.PcbDoc'
job = Job(id=identifier, filename='PCB comparison' if comparison else sources['file'][0],
status='queued', access=access, token_hash=hashlib.sha256(token.encode()).hexdigest(),
created_at=now, updated_at=now, expires_at=now+ttl, attempt=0, input_key=f'{identifier}/{input_name}')
created_at=now, updated_at=now, expires_at=expires_at, attempt=0, input_key=f'{identifier}/{input_name}')
if comparison:
bodies = {f'{identifier}/{side}.PcbDoc':sources[side+'_file'][1] for side in ('old','new')}
bodies[job.input_key] = json.dumps(dict(schema_version='1.0',document_type='pcb_comparison',
@@ -56,7 +56,7 @@ def register_pcb_routes(app, *, authorize, require_api, error):
try:
with sessions().begin() as db:
if db.bind.dialect.name == 'postgresql': db.execute(text('SELECT pg_advisory_xact_lock(84721309)'))
pending = db.scalar(select(func.count()).select_from(Job).where(Job.status.in_(['queued','processing']),Job.expires_at>now))
pending = db.scalar(select(func.count()).select_from(Job).where(Job.status.in_(['queued','processing']),active_jobs(now)))
if pending >= settings().max_pending: error('queue_full','Rendering queue is full; try again later',503)
for key, body in bodies.items():
# Include the attempted key so a write-then-raise backend is also cleaned up.
@@ -78,14 +78,14 @@ def register_pcb_routes(app, *, authorize, require_api, error):
@app.post('/api/v1/pcbs/render', status_code=202, response_model=PCBUploadResponse, response_model_exclude_none=True, tags=['PCB'])
async def render(file:Annotated[UploadFile,File()], access:Annotated[Literal['private','unlisted'],Form()]='private',
expires_in:Annotated[int|None,Form(gt=0)]=None, x_api_key:Annotated[str|None,Header()]=None):
expires_in:Annotated[int|None,Form(ge=-1, description="-1 for no expiry, or positive seconds")]=None, x_api_key:Annotated[str|None,Header()]=None):
require_api(x_api_key)
return await create({'file':file},access,expires_in,False)
@app.post('/api/v1/pcbs/comparisons',status_code=202,response_model=PCBComparisonUploadResponse,response_model_exclude_none=True,tags=['PCB'])
async def compare(old_file:Annotated[UploadFile,File()],new_file:Annotated[UploadFile,File()],
access:Annotated[Literal['private','unlisted'],Form()]='private',
expires_in:Annotated[int|None,Form(gt=0)]=None,x_api_key:Annotated[str|None,Header()]=None):
expires_in:Annotated[int|None,Form(ge=-1, description="-1 for no expiry, or positive seconds")]=None,x_api_key:Annotated[str|None,Header()]=None):
require_api(x_api_key)
return await create({'old_file':old_file,'new_file':new_file},access,expires_in,True)