func processRun( parentCtx *common.Context, client *http.Client, baseURL *url.URL, ) error { requestURL, err := baseURL.Parse("run/request/") if err != nil { panic(err) } resp, err := client.Get(requestURL.String()) if err != nil { return err } defer resp.Body.Close() ctx := parentCtx.DebugContext() syncID, err := strconv.ParseUint(resp.Header.Get("Sync-ID"), 10, 64) if err != nil { return err } ctx.EventCollector.Add(ctx.EventFactory.NewReceiverClockSyncEvent(syncID)) decoder := json.NewDecoder(resp.Body) var run common.Run if err := decoder.Decode(&run); err != nil { return err } uploadURL, err := baseURL.Parse(fmt.Sprintf("run/%d/results/", run.AttemptID)) if err != nil { return err } finished := make(chan error, 1) if err = gradeAndUploadResults( ctx, client, uploadURL.String(), &run, finished, ); err != nil { return err } return <-finished }
func gradeAndUploadResults( ctx *common.Context, client *http.Client, uploadURL string, run *common.Run, finished chan<- error, ) error { requestBody := NewChannelBuffer() defer requestBody.CloseChannel() multipartWriter := multipart.NewWriter(requestBody) defer multipartWriter.Close() go func() { defer requestBody.Close() req, err := http.NewRequest("POST", uploadURL, requestBody) if err != nil { finished <- err close(finished) return } req.Header.Add("Content-Type", multipartWriter.FormDataContentType()) response, err := client.Do(req) if err != nil { finished <- err close(finished) return } response.Body.Close() finished <- nil close(finished) }() result, err := gradeRun(ctx, client, run, multipartWriter) if err != nil { // Still try to send the details ctx.Log.Error("Error grading run", "err", err) result = &runner.RunResult{ Verdict: "JE", MaxScore: run.MaxScore, } } // Send results. resultWriter, err := multipartWriter.CreateFormFile("file", "details.json") if err != nil { ctx.Log.Error("Error sending details.json", "err", err) return err } encoder := json.NewEncoder(resultWriter) if err := encoder.Encode(result); err != nil { ctx.Log.Error("Error encoding details.json", "err", err) return err } // Send uncompressed logs. logsBuffer := ctx.LogBuffer() if logsBuffer != nil { logsWriter, err := multipartWriter.CreateFormFile("file", "logs.txt") if err != nil { ctx.Log.Error("Error creating logs.txt", "err", err) return err } if _, err = logsWriter.Write(logsBuffer); err != nil { ctx.Log.Error("Error sending logs.txt", "err", err) } } // Send uncompressed tracing data. traceBuffer := ctx.TraceBuffer() if traceBuffer != nil { tracingWriter, err := multipartWriter.CreateFormFile("file", "tracing.json") if err != nil { ctx.Log.Error("Error creating tracing.json", "err", err) return err } if _, err = tracingWriter.Write(traceBuffer); err != nil { ctx.Log.Error("Error sending tracing.json", "err", err) return err } } return nil }