package runner import ( "context" "encoding/json" "fmt" "git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/model" "git.0x7f.app/WOJ/woj-server/internal/service/runner" "git.0x7f.app/WOJ/woj-server/pkg/file" "git.0x7f.app/WOJ/woj-server/pkg/utils" "github.com/hibiken/asynq" "go.uber.org/zap" "path/filepath" "time" ) var ( statusSystemError = runner.JudgeStatus{ Message: "System Error", CompileMessage: "", Tasks: []runner.TaskStatus{{Verdict: runner.VerdictSystemError, Message: "System Error"}}, } ) func (h *handler) Judge(_ context.Context, t *asynq.Task) error { var p model.SubmitJudgePayload if err := json.Unmarshal(t.Payload(), &p); err != nil { return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry) } user := utils.RandomString(16) h.log.Debug("judge", zap.Any("payload", p), zap.String("user", user)) meta := runner.JudgeMeta{ Run: runner.JudgeMetaRun{ Version: p.ProblemVersionID, User: user, Lang: p.Submission.Language, }, } status, point, ctx := func() (e.Status, int32, *runner.JudgeStatus) { // 1. write user code userCode := filepath.Join(runner.UserDir, user, fmt.Sprintf("%s.%s", user, p.Submission.Language)) if !file.Touch(userCode) { return e.InternalError, 0, &statusSystemError } err := file.Write(userCode, []byte(p.Submission.Code)) if err != nil { return e.InternalError, 0, &statusSystemError } // 2. check problem if !h.runnerService.ProblemExists(&meta) { url, status := h.storageService.Get(p.StorageKey, time.Second*60*5) if status != e.Success { return status, 0, &statusSystemError } _, status = h.runnerService.NewProblem(&meta, url, false) if status != e.Success { return status, 0, &statusSystemError } } // 3. validate if ret, status := h.runnerService.ValidatePath(&meta); status != e.Success { return status, 0, ret } // 4. extract config if status := h.runnerService.GetConfig(&meta, true); status != e.Success { return e.RunnerProblemParseFailed, 0, &runner.JudgeStatus{ Message: fmt.Sprintf("System Error: Problem Malformed (%d:%s)", status, status.String()), CompileMessage: "", Tasks: []runner.TaskStatus{{Verdict: runner.VerdictSystemError, Message: "System Error"}}, } } // 5. compile compileResult, status := h.runnerService.Compile(&meta) if status != e.Success { return status, 0, compileResult } // 6. run and judge result, point, status := h.runnerService.RunAndJudge(&meta) result.CompileMessage = compileResult.CompileMessage return status, point, result }() if status == e.InternalError { // notice asynq to retry return fmt.Errorf("internal error, ctx: %v", *ctx) } h.taskService.SubmitUpdate(&model.SubmitUpdatePayload{ Status: status, SubmissionID: p.Submission.ID, ProblemVersionID: p.ProblemVersionID, UserDir: user, Point: point, }, *ctx) return nil }