From 76208424fb77ae38ffb5fbaaca25f7c3799e4445 Mon Sep 17 00:00:00 2001 From: Mark Saroufim Date: Thu, 18 Jun 2026 16:23:34 -0700 Subject: [PATCH 1/2] Expose submission job status to users --- src/kernelbot/api/main.py | 5 +++++ src/libkernelbot/db_types.py | 3 +++ src/libkernelbot/leaderboard_db.py | 7 ++++++- tests/test_leaderboard_db.py | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/kernelbot/api/main.py b/src/kernelbot/api/main.py index d9f98973b..6b98e1f4d 100644 --- a/src/kernelbot/api/main.py +++ b/src/kernelbot/api/main.py @@ -1008,6 +1008,11 @@ async def get_user_submission( "done": submission["done"], "code": submission["code"], "runs": [{k: r[k] for k in run_fields} for r in submission["runs"]], + "job": { + "status": submission.get("job_status"), + "error": submission.get("job_error"), + "last_heartbeat": submission.get("job_last_heartbeat"), + }, } except HTTPException: raise diff --git a/src/libkernelbot/db_types.py b/src/libkernelbot/db_types.py index ee1e84a35..75acdfa3d 100644 --- a/src/libkernelbot/db_types.py +++ b/src/libkernelbot/db_types.py @@ -60,6 +60,9 @@ class SubmissionItem(TypedDict): done: bool code: str runs: List[RunItem] + job_status: NotRequired[Optional[str]] + job_error: NotRequired[Optional[str]] + job_last_heartbeat: NotRequired[Optional[datetime.datetime]] class RateLimitItem(TypedDict): diff --git a/src/libkernelbot/leaderboard_db.py b/src/libkernelbot/leaderboard_db.py index 6169441ed..10857603d 100644 --- a/src/libkernelbot/leaderboard_db.py +++ b/src/libkernelbot/leaderboard_db.py @@ -1368,10 +1368,12 @@ def get_leaderboard_submission_ids( def get_submission_by_id(self, submission_id: int) -> Optional["SubmissionItem"]: query = """ SELECT s.leaderboard_id, lb.name, s.file_name, s.user_id, - s.submission_time, s.done, c.code + s.submission_time, s.done, c.code, + js.status, js.error, js.last_heartbeat FROM leaderboard.submission s JOIN leaderboard.code_files c ON s.code_id = c.id JOIN leaderboard.leaderboard lb ON s.leaderboard_id = lb.id + LEFT JOIN leaderboard.submission_job_status js ON js.submission_id = s.id WHERE s.id = %s """ self.cursor.execute(query, (submission_id,)) @@ -1416,6 +1418,9 @@ def get_submission_by_id(self, submission_id: int) -> Optional["SubmissionItem"] done=submission[5], code=bytes(submission[6]).decode("utf-8"), runs=runs, + job_status=submission[7], + job_error=submission[8], + job_last_heartbeat=submission[9], ) def get_leaderboard_submission_count( diff --git a/tests/test_leaderboard_db.py b/tests/test_leaderboard_db.py index 986ca919b..aaba37274 100644 --- a/tests/test_leaderboard_db.py +++ b/tests/test_leaderboard_db.py @@ -199,6 +199,16 @@ def test_leaderboard_submission_basic(database, submit_leaderboard): assert submission["done"] is False assert submission["code"] == dangerous_code assert submission["runs"] == [] + assert submission["job_status"] is None + assert submission["job_error"] is None + assert submission["job_last_heartbeat"] is None + + heartbeat = datetime.datetime.now(tz=datetime.timezone.utc) + db.upsert_submission_job_status(sub_id, "running", "still working", heartbeat) + submission = db.get_submission_by_id(sub_id) + assert submission["job_status"] == "running" + assert submission["job_error"] == "still working" + assert submission["job_last_heartbeat"] == heartbeat # add a submission run run_result = sample_run_result() From a55586aa856639b98a17bf592aa150e838a2b2d9 Mon Sep 17 00:00:00 2001 From: Mark Saroufim Date: Thu, 18 Jun 2026 16:33:10 -0700 Subject: [PATCH 2/2] Update backend submission expectations --- tests/test_backend.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_backend.py b/tests/test_backend.py index b4f01f35e..e443cef18 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -172,6 +172,9 @@ async def test_submit_leaderboard(bot: backend.KernelBackend, task_directory): "code": "pass", "done": False, "file_name": "submit.py", + "job_error": None, + "job_last_heartbeat": None, + "job_status": None, "leaderboard_id": s_id, "leaderboard_name": "submit-leaderboard", "runs": [ @@ -279,6 +282,9 @@ async def test_submit_full(bot: backend.KernelBackend, task_directory): "code": "pass", "done": True, "file_name": "submission.py", + "job_error": None, + "job_last_heartbeat": None, + "job_status": None, "leaderboard_id": 1, "leaderboard_name": "submit-leaderboard", "runs": [