feat(阶段2补课): SQL 判题链路 + 最后两个后台端点
新后端此前完全没有 SQL 判题(旧 judge/sql_runner.py 378 行 + sql_dispatcher.py 113 行无对应实现),阶段 2 纵切时漏了这条与沙箱完全不同的路径。 judge/sql/engine.ts 判题核心,移植自 sql_runner.py,判定口径逐条对齐 judge/sql/child.ts 子进程入口 judge/sql/index.ts 父进程:spawn + 硬超时 judge/run.ts language === "SQL" 时分流,不经判题沙箱 POST admin/sql-test-cases/preview 题目页展示数据预览 POST admin/sql-test-cases/generate AI 按标准答案倒推初始化脚本 题目保存时重新生成 sqlDisplay(对齐旧 generate_sql_display):取测试点 1 的初始化 脚本 + 标准答案跑一遍,失败一律拦下不让保存 —— 展示数据直接决定学生看到的表结构 与期望结果,宁可不保存也不能存错的。 ## 防护换了实现,逐条实测 bun:sqlite 没有 authorizer / progress_handler / setlimit,且实测 Worker.terminate() 杀不掉跑飞的查询(原生代码占着线程)。改用「WASM 引擎 + 独立子进程」: ATTACH → WASM 无宿主文件系统绑定,结构上够不到(比旧的 authorizer 更强) 查询题只读 → PRAGMA query_only=1 超时 → 子进程外部 SIGKILL 单值内存 → 子进程 ulimit -d 八条提交实测:正确→Accepted;列少一个/漏过滤→Wrong Answer;语法错误→Compile Error; 查询题里 INSERT→运行错误并说明;递归 CTE 死循环→CPU 超时;hex(zeroblob(2e8))→内存超限; attach '/etc/passwd'→打不开。 ## 踩到的两个坑(已写进 docs/specs/phase3-coverage.md) 1. ulimit 必须用 -d 不能用 -v。-v 限虚拟地址空间而 JS 引擎预留巨量地址,实测 -v 之下 Bun 退出时有概率 panic(SIGILL),结果早已写出但进程异常终止,父进程读到空串 误判成超时 —— 6 次里坏 2 次。换 -d 后 12/12 稳定。 2. 子进程写完结果直接 SIGKILL 自己,不走 process.exit()——后者仍有清理会撞限额。 至此 admin/api.ts 已无任何指向旧后端的调用。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
8
bun.lock
8
bun.lock
@@ -21,12 +21,14 @@
|
||||
"hono": "^4.0.0",
|
||||
"ioredis": "^6.0.0",
|
||||
"postgres": "^3.4.0",
|
||||
"sql.js": "^1.14.1",
|
||||
"tree-sitter-c": "^0.24.1",
|
||||
"tree-sitter-python": "^0.25.0",
|
||||
"web-tree-sitter": "^0.26.11",
|
||||
"zod": "^4.0.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/sql.js": "^1.4.11",
|
||||
"drizzle-kit": "^0.31.10",
|
||||
},
|
||||
},
|
||||
@@ -633,6 +635,8 @@
|
||||
|
||||
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "https://registry.npmjs.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
|
||||
|
||||
"@types/emscripten": ["@types/emscripten@1.41.5", "", {}, "sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.9", "https://registry.npmjs.com/@types/estree/-/estree-1.0.9.tgz", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
||||
|
||||
"@types/event-emitter": ["@types/event-emitter@0.3.5", "https://registry.npmjs.com/@types/event-emitter/-/event-emitter-0.3.5.tgz", {}, "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ=="],
|
||||
@@ -655,6 +659,8 @@
|
||||
|
||||
"@types/retry": ["@types/retry@0.12.2", "https://registry.npmjs.com/@types/retry/-/retry-0.12.2.tgz", {}, "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow=="],
|
||||
|
||||
"@types/sql.js": ["@types/sql.js@1.4.11", "", { "dependencies": { "@types/emscripten": "*", "@types/node": "*" } }, "sha512-QXIx38p2ZThJaK9vP5ZdqdlRe1FG9I8SmCZOS7FHfB/2qPAjZwkL7/vlfPg6N/oWHuuOaGg/P/IRwfP2W0kWVQ=="],
|
||||
|
||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "https://registry.npmjs.com/@types/trusted-types/-/trusted-types-2.0.7.tgz", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||
|
||||
"@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "https://registry.npmjs.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="],
|
||||
@@ -1321,6 +1327,8 @@
|
||||
|
||||
"source-map-support": ["source-map-support@0.5.21", "https://registry.npmjs.com/source-map-support/-/source-map-support-0.5.21.tgz", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
||||
|
||||
"sql.js": ["sql.js@1.14.1", "https://registry.npmjs.com/sql.js/-/sql.js-1.14.1.tgz", {}, "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A=="],
|
||||
|
||||
"ssr-window": ["ssr-window@4.0.2", "https://registry.npmjs.com/ssr-window/-/ssr-window-4.0.2.tgz", {}, "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="],
|
||||
|
||||
"standard-as-callback": ["standard-as-callback@2.1.0", "https://registry.npmjs.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
|
||||
|
||||
Reference in New Issue
Block a user