fix(判题): SQL 题判题也排队占名额,和别的判题一起抢那两个核时不再被误判超时
SQL 子进程在 worker 里跑,原来不经判题名额(judge/slots.ts):两道 SQL、两道沙箱判题、 再加流程图试运行可以同时压在服务器两个核上,SQL 的时限按墙钟算,挤的时候本来不超时的 语句会被判成超时。现在和沙箱判题占同一个池,一个名额管整份提交,租约按每个测试点 最长可能占的时间算。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
38a331c2b7
commit
bc42ade705
2 files changed
+28
-1
No files matched your search
@@ -14,7 +14,7 @@ import type { JudgeJobData } from './job'
|
||||
import { isAccepted, JudgeStatus, type JudgeStatusValue } from './status'
|
||||
import { parseProblemTemplate, shiftCompileLines } from './template'
|
||||
import { withJudgeSlot } from './slots'
|
||||
import { runSqlCase } from './sql'
|
||||
import { runSqlCase, sqlCaseBudgetMs } from './sql'
|
||||
import { nativeRuntimeError, parsePythonTraceback, type RuntimeErrorInfo } from './runtime-diagnosis'
|
||||
import { compileError, judge, JudgeUnreachableError, type JudgeCase, type JudgeResponse } from './sandbox'
|
||||
import { readInfo } from '../services/test-case'
|
||||
@@ -625,6 +625,25 @@ async function judgeSqlSubmission(problem: typeof schema.problem.$inferSelect, s
|
||||
const keys = Object.keys(info.test_cases ?? {}).sort((a, b) => Number(a) - Number(b))
|
||||
if (keys.length === 0) throw new Error('题目没有任何测试点')
|
||||
|
||||
/**
|
||||
* 和沙箱判题占同一个池的名额(judge/slots.ts):SQL 子进程在 worker 里跑,同样吃服务器
|
||||
* 那两个核,原来不排队 —— 两道 SQL 加两道沙箱判题、再加流程图试运行一起压上去,
|
||||
* 按墙钟算的 SQL 时限就会把本来不超时的语句判成超时。一个名额管整份提交,和沙箱那边一样。
|
||||
* 租约按每个测试点最长可能占的时间算,再加 30 秒
|
||||
*/
|
||||
const holdMs = keys.length * sqlCaseBudgetMs(problem.timeLimit) + 30_000
|
||||
return withJudgeSlot('judge', { holdMs }, () => judgeSqlCases(problem, keys, info, refSql, studentSql, mode, sqlConfig))
|
||||
}
|
||||
|
||||
async function judgeSqlCases(
|
||||
problem: typeof schema.problem.$inferSelect,
|
||||
keys: string[],
|
||||
info: NonNullable<Awaited<ReturnType<typeof readInfo>>>,
|
||||
refSql: string,
|
||||
studentSql: string,
|
||||
mode: 'query' | 'modify',
|
||||
sqlConfig: Record<string, unknown>,
|
||||
): Promise<JudgeResponse> {
|
||||
const cases: JudgeCase[] = []
|
||||
for (const [index, key] of keys.entries()) {
|
||||
const inputName = info.test_cases![key]!.input_name
|
||||
|
||||
@@ -172,6 +172,14 @@ async function runJob<T>(job: SqlJob, budget: JobBudget): Promise<SqlJobOutcome<
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个测试点最长可能占多久:受信阶段的预算 + 启动余量,进了学生阶段换成题目时限 + 余量。
|
||||
* 判题名额的租约(judge/slots.ts)按它算,租约比这短的话跑到一半名额会被别人拿走
|
||||
*/
|
||||
export function sqlCaseBudgetMs(timeLimitMs: number) {
|
||||
return trustedBudgetMs(timeLimitMs) + STARTUP_SLACK_MS + timeLimitMs + STUDENT_SLACK_MS
|
||||
}
|
||||
|
||||
export function runSqlCase(job: Extract<SqlJob, { kind: 'judge' }>) {
|
||||
return runJob<CaseResult>(job, {
|
||||
trustedMs: trustedBudgetMs(job.timeLimitMs),
|
||||
|
||||
Reference in new issue
Block a user