|
2 | 2 |
|
3 | 3 | from fastapi import APIRouter, Depends, HTTPException
|
4 | 4 | from sqlalchemy.ext.asyncio import AsyncSession
|
5 |
| -from sqlalchemy import select, delete, desc, func, update, and_ |
| 5 | +from sqlalchemy import select, desc, func, update, and_ |
6 | 6 | from sqlalchemy.exc import IntegrityError
|
7 | 7 | from datetime import datetime
|
8 | 8 | import logging
|
9 | 9 |
|
10 | 10 | from .. import schemas, crud, models
|
11 |
| -from ..database import get_database, transaction_scope |
| 11 | +from ..database import get_database |
12 | 12 | from ..auth import get_current_token
|
13 | 13 |
|
14 | 14 | router = APIRouter(prefix="/api", tags=["upload"])
|
@@ -75,7 +75,7 @@ async def cleanup_old_flamegraphs_if_needed(
|
75 | 75 | )
|
76 | 76 |
|
77 | 77 | try:
|
78 |
| - result = await db.execute(cleanup_query) |
| 78 | + await db.execute(cleanup_query) |
79 | 79 | await db.commit()
|
80 | 80 |
|
81 | 81 | verify_result = await db.execute(count_query)
|
@@ -261,7 +261,7 @@ def clean_flag(flag):
|
261 | 261 | )
|
262 | 262 |
|
263 | 263 | try:
|
264 |
| - new_run = await crud.create_run(db, run_data) |
| 264 | + await crud.create_run(db, run_data) |
265 | 265 | logger.info(f"Successfully created run record: {run_id}")
|
266 | 266 |
|
267 | 267 | # Create benchmark results
|
@@ -355,3 +355,122 @@ def clean_flag(flag):
|
355 | 355 | raise HTTPException(
|
356 | 356 | status_code=500, detail=f"Failed to upload worker run: {str(e)}"
|
357 | 357 | )
|
| 358 | + |
| 359 | + |
| 360 | +@router.post("/report-memray-failure", response_model=dict) |
| 361 | +async def report_memray_failure( |
| 362 | + failure_data: schemas.MemrayFailureReport, |
| 363 | + db: AsyncSession = Depends(get_database), |
| 364 | + current_token: models.AuthToken = Depends(get_current_token), |
| 365 | +): |
| 366 | + """Report a memray build failure for a specific commit and environment.""" |
| 367 | + logger = logging.getLogger(__name__) |
| 368 | + |
| 369 | + logger.info( |
| 370 | + f"Authenticated memray failure report from token '{current_token.name}' for commit {failure_data.commit_sha[:8]}, " |
| 371 | + f"binary_id='{failure_data.binary_id}', environment_id='{failure_data.environment_id}'" |
| 372 | + ) |
| 373 | + |
| 374 | + # Validate binary exists |
| 375 | + binary = await crud.get_binary_by_id(db, binary_id=failure_data.binary_id) |
| 376 | + if not binary: |
| 377 | + logger.error(f"Memray failure report failed: Binary '{failure_data.binary_id}' not found") |
| 378 | + raise HTTPException( |
| 379 | + status_code=400, |
| 380 | + detail=f"Binary '{failure_data.binary_id}' not found." |
| 381 | + ) |
| 382 | + |
| 383 | + # Validate environment exists |
| 384 | + environment = await crud.get_environment_by_id(db, environment_id=failure_data.environment_id) |
| 385 | + if not environment: |
| 386 | + logger.error(f"Memray failure report failed: Environment '{failure_data.environment_id}' not found") |
| 387 | + raise HTTPException( |
| 388 | + status_code=400, |
| 389 | + detail=f"Environment '{failure_data.environment_id}' not found." |
| 390 | + ) |
| 391 | + |
| 392 | + # Create or get commit |
| 393 | + commit = await crud.get_commit_by_sha(db, sha=failure_data.commit_sha) |
| 394 | + if not commit: |
| 395 | + logger.info(f"Commit {failure_data.commit_sha[:8]} not found, creating new commit record") |
| 396 | + # Create minimal commit record - we'll update it with full metadata later if needed |
| 397 | + commit_data = schemas.CommitCreate( |
| 398 | + sha=failure_data.commit_sha, |
| 399 | + timestamp=failure_data.commit_timestamp, |
| 400 | + message="Commit with memray build failure", |
| 401 | + author="Unknown", |
| 402 | + python_version=schemas.PythonVersion(major=3, minor=12, patch=0) # Default values |
| 403 | + ) |
| 404 | + try: |
| 405 | + commit = await crud.create_commit(db, commit_data) |
| 406 | + logger.info(f"Successfully created minimal commit record for {failure_data.commit_sha[:8]}") |
| 407 | + except Exception as e: |
| 408 | + logger.error(f"Failed to create commit record for {failure_data.commit_sha[:8]}: {e}") |
| 409 | + raise HTTPException( |
| 410 | + status_code=500, detail=f"Failed to create commit record: {str(e)}" |
| 411 | + ) |
| 412 | + |
| 413 | + # Check if this failure is newer than any existing failure for this binary+environment |
| 414 | + existing_failure = await db.execute( |
| 415 | + select(models.MemrayBuildFailure) |
| 416 | + .where( |
| 417 | + models.MemrayBuildFailure.binary_id == failure_data.binary_id, |
| 418 | + models.MemrayBuildFailure.environment_id == failure_data.environment_id |
| 419 | + ) |
| 420 | + ) |
| 421 | + existing_failure = existing_failure.scalars().first() |
| 422 | + |
| 423 | + if existing_failure: |
| 424 | + # Check if the new failure is from a newer commit |
| 425 | + if failure_data.commit_timestamp <= existing_failure.commit_timestamp: |
| 426 | + logger.info( |
| 427 | + f"Ignoring memray failure for {failure_data.commit_sha[:8]} as it's not newer than existing failure" |
| 428 | + ) |
| 429 | + return { |
| 430 | + "message": "Memray failure ignored (not newer than existing failure)", |
| 431 | + "commit_sha": failure_data.commit_sha, |
| 432 | + "binary_id": failure_data.binary_id, |
| 433 | + "environment_id": failure_data.environment_id, |
| 434 | + } |
| 435 | + |
| 436 | + # Update existing failure with newer information |
| 437 | + existing_failure.commit_sha = failure_data.commit_sha |
| 438 | + existing_failure.error_message = failure_data.error_message |
| 439 | + existing_failure.failure_timestamp = datetime.now() |
| 440 | + existing_failure.commit_timestamp = failure_data.commit_timestamp |
| 441 | + |
| 442 | + try: |
| 443 | + await db.commit() |
| 444 | + logger.info(f"Updated existing memray failure record for binary '{failure_data.binary_id}', environment '{failure_data.environment_id}'") |
| 445 | + except Exception as e: |
| 446 | + logger.error(f"Failed to update memray failure record: {e}") |
| 447 | + raise HTTPException( |
| 448 | + status_code=500, detail=f"Failed to update memray failure record: {str(e)}" |
| 449 | + ) |
| 450 | + else: |
| 451 | + # Create new failure record |
| 452 | + failure_record = models.MemrayBuildFailure( |
| 453 | + commit_sha=failure_data.commit_sha, |
| 454 | + binary_id=failure_data.binary_id, |
| 455 | + environment_id=failure_data.environment_id, |
| 456 | + error_message=failure_data.error_message, |
| 457 | + failure_timestamp=datetime.now(), |
| 458 | + commit_timestamp=failure_data.commit_timestamp |
| 459 | + ) |
| 460 | + |
| 461 | + try: |
| 462 | + db.add(failure_record) |
| 463 | + await db.commit() |
| 464 | + logger.info(f"Created new memray failure record for commit {failure_data.commit_sha[:8]}") |
| 465 | + except Exception as e: |
| 466 | + logger.error(f"Failed to create memray failure record: {e}") |
| 467 | + raise HTTPException( |
| 468 | + status_code=500, detail=f"Failed to create memray failure record: {str(e)}" |
| 469 | + ) |
| 470 | + |
| 471 | + return { |
| 472 | + "message": "Memray failure reported successfully", |
| 473 | + "commit_sha": failure_data.commit_sha, |
| 474 | + "binary_id": failure_data.binary_id, |
| 475 | + "environment_id": failure_data.environment_id, |
| 476 | + } |
0 commit comments