/
main.go
106 lines (97 loc) · 2.78 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"time"
"github.com/go-martini/martini"
graphql "github.com/hasura/go-graphql-client"
executor "github.com/maratona-run-time/Maratona-Runtime/executor/src"
model "github.com/maratona-run-time/Maratona-Runtime/model"
"github.com/maratona-run-time/Maratona-Runtime/utils"
"github.com/martini-contrib/binding"
"github.com/rs/zerolog"
)
// FileForm receives a submission ID
type FileForm struct {
ID string `form:"id"`
}
type (
Input struct {
FileName string
Content []byte
}
Challenge struct {
TimeLimit float32
Inputs []Input
}
Submission struct {
Challenge Challenge
}
Info struct {
Submission Submission `graphql:"submission(id: $id)"`
}
)
func createExecutorServer(client utils.QueryClient, logger zerolog.Logger, serverChannel chan int) *martini.ClassicMartini {
m := martini.Classic()
m.Post("/", binding.MultipartForm(FileForm{}), func(rs http.ResponseWriter, rq *http.Request, req FileForm) []byte {
serverChannel <- 0
defer func() {
serverChannel <- 0
}()
var info Info
variables := map[string]interface{}{
"id": graphql.ID(req.ID),
}
graphqlErr := client.Query(context.Background(), &info, variables)
if graphqlErr != nil {
msg := "An error occurred while trying to fetch submission '" + req.ID + "' details"
logger.Error().
Err(graphqlErr).
Msg(msg)
utils.WriteResponse(rs, http.StatusBadRequest, msg, graphqlErr)
return nil
}
os.Mkdir("inputs", 0700)
for _, input := range info.Submission.Challenge.Inputs {
testFileName := fmt.Sprintf("inputs/%s", input.FileName)
writeErr := ioutil.WriteFile(testFileName, input.Content, 0777)
if writeErr != nil {
msg := "An error occurred while trying to write the received test to a local file named '" + testFileName
utils.WriteResponse(rs, http.StatusInternalServerError, msg, writeErr)
logger.Error().
Err(writeErr).
Msg(msg)
return nil
}
}
res := executor.Execute("/var/program.out", "inputs", info.Submission.Challenge.TimeLimit, logger)
jsonResult, convertErr := json.Marshal(res)
if convertErr != nil {
msg := "An error occurred while trying to convert the execution result into a json format"
utils.WriteResponse(rs, http.StatusInternalServerError, msg, convertErr)
logger.Error().
Err(convertErr).
Msg(msg)
return nil
}
return jsonResult
})
return m
}
func main() {
logger, logFile := utils.InitLogger("executor")
defer logFile.Close()
client := graphql.NewClient("http://orm:8084/graphql", nil)
serverChannel := make(chan int)
m := createExecutorServer(client, logger, serverChannel)
go m.RunOnAddr(":8082")
select {
case <-serverChannel:
<-serverChannel
case <-time.After(model.CONTAINER_TIMEOUT_MINUTES * time.Minute):
}
}