feat(rejudge): support pull mode and snapshot-based judging#139
feat(rejudge): support pull mode and snapshot-based judging#139thezzisu wants to merge 3 commits into
Conversation
Deploying aoi with
|
| Latest commit: |
ce23630
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b692b9b4.aoi-b5x.pages.dev |
| Branch Preview URL: | https://fix-pull-rejudge-ui.aoi-b5x.pages.dev |
There was a problem hiding this comment.
Pull request overview
This PR adds explicit “fixed vs pull” rejudge controls for admins and switches runner polling to judge against the solution/instance’s snapshot (problemDataHash) rather than the mutable problem head, while preventing deletion of problem data versions that are still referenced.
Changes:
- Backend: add
pullsupport to single-solution rejudge endpoints and contest admin advanced rejudge; runner polling now loads problem config/data by snapshot hash. - Backend: block deletion of problem data versions referenced by any solution or instance.
- Frontend: add fixed/pull toggles to single-solution admin rejudge and contest admin advanced rejudge UI.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| apps/server/src/routes/runner/solution.ts | Runner solution polling now uses solution.problemDataHash snapshot for config/data URL. |
| apps/server/src/routes/runner/instance.ts | Runner instance polling now uses instance.problemDataHash snapshot for config/data URL. |
| apps/server/src/routes/problem/solution.ts | Non-contest solution rejudge endpoint now accepts { pull?: boolean } and optionally updates snapshot fields. |
| apps/server/src/routes/problem/data.ts | Prevent deleting a problem data version if referenced by any solution/instance. |
| apps/server/src/routes/contest/solution/index.ts | Contest solution rejudge endpoint now accepts { pull?: boolean } and can repin to current data. |
| apps/server/src/routes/contest/admin.ts | Advanced rejudge-all now supports pull mode and cross-problem label/hash repinning. |
| apps/frontend/src/pages/org/[orgId]/contest/[contestId]/admin/index.vue | Add fixed/pull toggle and send pull for contest admin rejudge-all. |
| apps/frontend/src/components/solution/SolutionView.vue | Add fixed/pull toggle UI for admin rejudge. |
| apps/frontend/src/components/solution/SolutionView.ts | Send { pull } in rejudge request and expose pull state to the view. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let modifiedCount = 0 | ||
| for (const problem of matchedProblems) { | ||
| const currentData = problem.data.find(({ hash }) => hash === problem.currentDataHash) | ||
| if (!currentData) return rep.preconditionFailed('Current data not found') |
There was a problem hiding this comment.
In pull-mode, this endpoint updates solutions problem-by-problem in a loop and can return preconditionFailed('Current data not found') mid-way. That leaves any earlier updateMany calls already applied, resulting in a partial rejudge that’s hard to reason about/rollback. Consider validating all matched problems up-front (existence + currentDataHash present in data) before issuing any updates, or performing the updates in a single bulk/transactional operation so failures don’t leave partial state.
| let modifiedCount = 0 | |
| for (const problem of matchedProblems) { | |
| const currentData = problem.data.find(({ hash }) => hash === problem.currentDataHash) | |
| if (!currentData) return rep.preconditionFailed('Current data not found') | |
| // Validate that all matched problemIds have corresponding problems and current data | |
| if (matchedProblems.length !== matchedProblemIds.length) { | |
| return rep.preconditionFailed('Current data not found') | |
| } | |
| for (const problem of matchedProblems) { | |
| const currentData = problem.data.find(({ hash }) => hash === problem.currentDataHash) | |
| if (!currentData) { | |
| return rep.preconditionFailed('Current data not found') | |
| } | |
| } | |
| let modifiedCount = 0 | |
| for (const problem of matchedProblems) { | |
| const currentData = problem.data.find(({ hash }) => hash === problem.currentDataHash) |
Summary
problemDataHashinstead of the mutable problem headChanges
Frontend
Backend
pullTest plan
yarn workspace @aoi-js/server type-checkyarn workspace @aoi-js/frontend type-check