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" ) 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{Version: p.ProblemVersionID, User: user, Lang: p.Submission.Language} SystemError := &runner.JudgeStatus{ Message: "System Error", Tasks: []runner.TaskStatus{{Verdict: runner.VerdictSystemError, Message: "API Error"}}, } 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, SystemError } err := file.Write(userCode, []byte(p.Submission.Code)) if err != nil { return e.InternalError, 0, SystemError } // 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, SystemError } _, status = h.runnerService.NewProblem(&meta, url, false) if status != e.Success { return status, 0, SystemError } } // 3. compile compileResult, status := h.runnerService.Compile(&meta) if status != e.Success { return status, 0, compileResult } // 4. run and judge result, point, status := h.runnerService.RunAndJudge(&meta) 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 }