Files
KF-OnlineJudge/backend/src/kf_oj/modules/submissions/README.md
T

4.4 KiB
Raw Blame History

submissions

负责提交幂等请求、不可变源码引用、创建初始评测、历史查询与学生可见结果。 创建提交、评测和待投递事件必须处于同一事务。 协调器拥有领取后的执行状态与最终结果写入权;本模块不能绕过协议覆盖终态。 queries.py 提供已验证主体的提交历史、详情与私有源码读取,其他账号不可读取; 历史按创建时间/UUID降序游标翻页,一次至多100条。读取完整成绩时严格核对报告契约和 评测绑定,仅投影允许公开的诊断/计量/测试点序号。取消通过注入的 Coordinator 控制 端口接受意图,不更新执行状态;202与清理完成的终态不同。 worker_access.py 核对当前 evaluation / attempt / Worker / fencing、未撤销及未过期凭证、 固定 submission 与版本及任务清单摘要;只允许读取该清单声明的工件。 内部 API 使用 WorkerLease bearer 和 X-Worker-ID / X-Fencing-Version,不使用用户会话授权。 允许状态为 claimed / compiling / running;取消请求、终态和旧 attempt 均拒绝。 字节准备后再次核对当前租约;最多同时两个有限读取,超过直接 429,不排无界等待队列。

任务清单为 UTF-8 JSON、对象键递归排序、无额外空白,并以这些确切字节的 SHA-256 标识。 Python/Rust manifest_bytes 与共享字节样例保持一致;Coordinator 必须用同一序列化定义存快照。 读取凭证与客户端提交的身份分开:身份和归属从实际数据库绑定获得,不接受客户端自报 user ID。

service.py 按账号与幂等UUID绑定版本/语言/源码摘要,持久化源码后同一事务创建 submission、queued evaluation 和 outbox;同键同内容复用既有提交,不同内容409。 待评测固定总量64、个人8,取消清理中也占用容量;配置或容量不足明确拒绝。 Coordinator 通过正式 claim 创建短期领取权,Worker 不写业务数据库。 真实服务链与安全条件必须在独立 VM 验收;数据库 fixture 的租约或合成报告只能 验证控制规则、授权和投影,不能作为真实程序执行/停止证明。

performance.py 提供本人提交的只读匿名聚合。Coordinator 在受验证最终 AC 的同一事务 写入不可变 evaluation_performance;平台只有 SELECT 权限。比较组绑定不可变版本、 语言、精确镜像/工具链、编译与运行预算,以及运维核验后配置的测量环境纪元。 没有原纪元的旧尝试不会通过当前配置被补造可信性,仍保留个人历史与正常成绩。 单条受控回填与纪元变更规则见协调器说明。

历史可按 problem_version_id 与可选 wire language 过滤,始终带当前账号条件。 GET /api/v1/submissions/{submission_id}/performance 每次先检查会话和所有权; 匿名拒绝、其他主体与不存在记录同为不可用,私有响应为 no-store。 缓存命中仍查归属。每进程最多一个聚合查询,不排等待队列;SQL 期限两秒、请求总期限 三秒、锁等待至多半秒。聚合 DTO 缓存三十秒且最多128项,新 AC 的索引水位改变即失效。 缓存不保存逐条样本数组,不向浏览器发送其他账号的身份、源码或逐条用量。

每指标在同一个只读可重复读快照内,排除当前提交,取最近最多10,000条非缺测的其他 有效 AC,响应带快照、最早样本及截断标志。少于五条时仅显示本次真实用量。 CPU 为测试点运行 CPU 微秒之和,内存为测试点运行峰值字节的最大值,不包括编译。 用量与桶边界以十进制字符串传输;零合法、缺测不补零。严格优于数按原整数的 > 计算,同值独立计数。响应至多24个连续桶,只有最后上界包含端点;浏览器仅格式化单位 和绘制坐标,比例以服务端严格计数除以样本数,不按人数统计。

下架只阻止新提交与公开题目读取。Worker 的版本读取通过 ProblemPort.for_accepted_execution, 在本模块验证当前 Coordinator 租约/尝试/源码绑定之后才调用;生成并比较原 canonical 快照,再次核对租约后才释放字节。无有效租约、外来工件、未发布版本和其他提交仍拒绝。 本人历史和源码读取保留所有权检查,不依赖题目当前 enabled 状态。