Skip to content

Commit cafaf47

Browse files
Artem TitovArtem Titov
authored andcommitted
Merge branch 'main' into dev/storage
2 parents 5bff50e + 6e7c312 commit cafaf47

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1363
-269
lines changed

common/config/config.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type Config struct {
1515
LogLevel *int `yaml:"LogLevel,omitempty"`
1616

1717
Invoker *InvokerConfig `yaml:"Invoker,omitempty"`
18-
Storage *StorageConfig `yaml:"Invoker,omitempty"`
18+
Storage *StorageConfig `yaml:"Storage,omitempty"`
1919
// TODO: Add instances here
2020

2121
DB DBConfig `yaml:"DB"`
@@ -47,4 +47,10 @@ func fillInConfig(config *Config) {
4747
}
4848

4949
fillInConnections(config)
50+
if config.Invoker != nil {
51+
fillInInvokerConfig(config.Invoker)
52+
}
53+
if config.Storage != nil {
54+
FillInStorageConfig(config.Storage)
55+
}
5056
}

common/config/connection.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ type Connection struct {
66
}
77

88
func fillInConnections(config *Config) {
9-
// TODO: Add auto connection creation if master or storageconn are set up
9+
// TODO: Add auto connection creation if master or storage are set up
1010
}

common/config/invoker.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
package config
22

3-
import "github.com/xorcare/pointer"
4-
53
type InvokerConfig struct {
6-
Instances int `yaml:"Instances"`
7-
QueueSize *int `yaml:"QueueSize,omitempty"` // default is 10
4+
Threads uint64 `yaml:"Threads"`
5+
Sandboxes uint64 `yaml:"Sandboxes"`
6+
QueueSize uint64 `yaml:"QueueSize"`
87

98
CacheSize uint64 `yaml:"CacheSize"`
109
CachePath string `yaml:"CachePath"`
10+
11+
SaveOutputHead *uint64 `yaml:"SaveOutputHead,omitempty"`
12+
13+
CompilerConfigsFolder string `yaml:"CompilerConfigsFolder"`
1114
}
1215

1316
func fillInInvokerConfig(config *InvokerConfig) {
14-
if config.QueueSize == nil {
15-
config.QueueSize = pointer.Int(10)
17+
if config.Threads == 0 {
18+
config.Threads = 1
19+
}
20+
if config.Sandboxes == 0 {
21+
// TODO: find out what number is the best
22+
config.Sandboxes = 1
23+
}
24+
if config.QueueSize == 0 {
25+
config.QueueSize = 10
1626
}
1727
if len(config.CachePath) == 0 {
1828
panic("No invoker cache path specified")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package connectors
2+
3+
import (
4+
"github.com/go-resty/resty/v2"
5+
"testing_system/common/config"
6+
)
7+
8+
type ConnectorBase struct {
9+
Connection *config.Connection
10+
client *resty.Client
11+
}
12+
13+
func NewConnectorBase(connection *config.Connection) *ConnectorBase {
14+
c := &ConnectorBase{
15+
Connection: connection,
16+
client: resty.New(),
17+
}
18+
// TODO: Add host initialization from connection
19+
// TODO: Add auth
20+
// TODO: Add retry configuration
21+
return c
22+
}
23+
24+
func (c *ConnectorBase) R() *resty.Request {
25+
return c.client.R()
26+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package invokerconn
2+
3+
import (
4+
"github.com/go-resty/resty/v2"
5+
"testing_system/common/config"
6+
"testing_system/common/connectors"
7+
"testing_system/lib/connector"
8+
)
9+
10+
type Connector struct {
11+
connection *connectors.ConnectorBase
12+
}
13+
14+
func NewConnector(connection *config.Connection) *Connector {
15+
return &Connector{connectors.NewConnectorBase(connection)}
16+
}
17+
18+
func (c *Connector) Status() (*StatusResponse, error) {
19+
r := c.connection.R()
20+
21+
return connector.Receive[StatusResponse](r, "/invoker/status", resty.MethodGet)
22+
}
23+
24+
func (c *Connector) NewJob(job *Job) (*StatusResponse, error) {
25+
r := c.connection.R()
26+
r.SetBody(job)
27+
28+
return connector.Receive[StatusResponse](r, "/invoker/job/new", resty.MethodPost)
29+
}
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
package invokerconn
22

3-
import (
4-
"testing_system/common/db/models"
5-
)
6-
7-
// This will be changed in later commits
3+
type JobType int
84

95
const (
10-
JobTypeCompile = iota
11-
JobTypeTest
6+
CompileJob JobType = iota
7+
TestJob
128
)
139

1410
type Job struct {
15-
SubmitID uint `json:"submitID" binding:"required"`
16-
JobType int `json:"jobType" binding:"required"`
17-
Test int `json:"test"`
11+
ID string `json:"ID"`
12+
SubmitID uint `json:"SubmitID" binding:"required"`
13+
Type JobType `json:"JobType" binding:"required"`
14+
Test uint64 `json:"Test"`
15+
16+
// TODO: Add job dependency
17+
}
1818

19-
Submit *models.Submission `json:"submit,omitempty"`
20-
Problem *models.Problem `json:"problem,omitempty"`
19+
type StatusResponse struct {
20+
// TODO: add some information about invoker state
21+
MaxNewJobs uint64 `json:"MaxNewJobs"`
22+
ActiveJobIDs []string `json:"ActiveJobIDs"`
2123
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package masterconn
2+
3+
import "testing_system/common/config"
4+
5+
type Connector struct {
6+
// TODO: Add master connection
7+
}
8+
9+
func NewConnector(connection *config.Connection) *Connector {
10+
return nil
11+
}
12+
13+
func (c *Connector) InvokerJobResult(result *InvokerJobResult) error {
14+
return nil
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package masterconn
2+
3+
import (
4+
"testing_system/common/connectors/invokerconn"
5+
"testing_system/common/constants/verdict"
6+
)
7+
8+
type InvokerJobResult struct {
9+
JobID string `json:"JobID"`
10+
Verdict verdict.Verdict `json:"Verdict"`
11+
Error string `json:"Error,omitempty"` // Is set only in case of check failed
12+
13+
InvokerStatus *invokerconn.StatusResponse `json:"InvokerStatus"`
14+
15+
// TODO: Add some statistics (e.g time, memory, etc)
16+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package storageconn
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"testing_system/common/config"
8+
"testing_system/common/connectors"
9+
"testing_system/common/constants/resource"
10+
11+
"github.com/go-resty/resty/v2"
12+
)
13+
14+
type Connector struct {
15+
connection *connectors.ConnectorBase
16+
}
17+
18+
func NewConnector(connection *config.Connection) *Connector {
19+
if connection == nil {
20+
return nil
21+
}
22+
return &Connector{connectors.NewConnectorBase(connection)}
23+
}
24+
25+
func (s *Connector) Download(request *Request) *ResponseFiles {
26+
if err := os.MkdirAll(request.BaseFolder, 0775); err != nil {
27+
return &ResponseFiles{Response: Response{R: *request, Error: fmt.Errorf("failed to create base folder: %v", err)}}
28+
}
29+
30+
path := fmt.Sprintf("/storage/get?id=%d&dataType=%s&filepath=%s",
31+
getIDForResource(request),
32+
getDataTypeForResource(request.Resource),
33+
request.Resource.String(),
34+
)
35+
36+
r := s.connection.R()
37+
resp, err := r.Execute(resty.MethodGet, path)
38+
if err != nil {
39+
return &ResponseFiles{Response: Response{R: *request, Error: fmt.Errorf("failed to send request: %v", err)}}
40+
}
41+
42+
if resp.IsError() {
43+
return &ResponseFiles{Response: Response{R: *request, Error: fmt.Errorf("request failed with status: %v", resp.Status())}}
44+
}
45+
46+
filename := request.Resource.String()
47+
if request.CustomFilename != "" {
48+
filename = request.CustomFilename
49+
}
50+
51+
filepath := filepath.Join(request.BaseFolder, filename)
52+
err = os.WriteFile(filepath, resp.Body(), 0644)
53+
if err != nil {
54+
return &ResponseFiles{Response: Response{R: *request, Error: fmt.Errorf("failed to write file: %v", err)}}
55+
}
56+
57+
responseFiles := NewResponseFiles(*request)
58+
responseFiles.fileNames = []string{filename}
59+
responseFiles.Size = uint64(len(resp.Body()))
60+
return responseFiles
61+
}
62+
63+
func (s *Connector) Upload(request *Request) *Response {
64+
if len(request.Files) == 0 {
65+
return &Response{R: *request, Error: fmt.Errorf("no files to upload")}
66+
}
67+
68+
path := fmt.Sprintf("/storage/upload?id=%d&dataType=%s&filepath=%s",
69+
getIDForResource(request),
70+
getDataTypeForResource(request.Resource),
71+
request.Resource.String(),
72+
)
73+
74+
r := s.connection.R()
75+
for filename, reader := range request.Files {
76+
r.SetFileReader("file", filename, reader)
77+
}
78+
79+
resp, err := r.Execute(resty.MethodPost, path)
80+
if err != nil {
81+
return &Response{R: *request, Error: fmt.Errorf("failed to send request: %v", err)}
82+
}
83+
84+
if resp.IsError() {
85+
return &Response{R: *request, Error: fmt.Errorf("request failed with status: %s, body: %s", resp.Status(), resp.String())}
86+
}
87+
88+
return &Response{R: *request}
89+
}
90+
91+
func (s *Connector) Delete(request *Request) *Response {
92+
path := fmt.Sprintf("/storage/remove?id=%d&dataType=%s&filepath=%s",
93+
getIDForResource(request),
94+
getDataTypeForResource(request.Resource),
95+
request.Resource.String(),
96+
)
97+
98+
r := s.connection.R()
99+
resp, err := r.Execute(resty.MethodDelete, path)
100+
if err != nil {
101+
return &Response{R: *request, Error: fmt.Errorf("failed to send request: %v", err)}
102+
}
103+
104+
if resp.IsError() {
105+
return &Response{R: *request, Error: fmt.Errorf("request failed with status: %s, body: %s", resp.Status(), resp.String())}
106+
}
107+
108+
return &Response{R: *request}
109+
}
110+
111+
func getIDForResource(request *Request) uint64 {
112+
switch request.Resource {
113+
case resource.SourceCode, resource.CompiledBinary, resource.CompileOutput:
114+
return request.SubmitID
115+
case resource.Checker, resource.Interactor:
116+
return request.ProblemID
117+
case resource.Test:
118+
if request.TestID > 0 {
119+
return request.TestID
120+
}
121+
return request.ProblemID
122+
default:
123+
return 0
124+
}
125+
}
126+
127+
func getDataTypeForResource(resourceType resource.Type) string {
128+
switch resourceType {
129+
case resource.SourceCode, resource.CompiledBinary, resource.CompileOutput:
130+
return "submission"
131+
case resource.Checker, resource.Interactor, resource.Test:
132+
return "problem"
133+
default:
134+
return "unknown"
135+
}
136+
}

common/connectors/storageconn/resourcetype_string.go

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)