aboutsummaryrefslogtreecommitdiffhomepage
path: root/backend
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-08-08 21:17:06 +0900
committernsfisis <nsfisis@gmail.com>2024-08-08 21:17:06 +0900
commit3b13a61123becc63823ab0c0941aaff2048b020e (patch)
treee2e48d8d92e2601d65e3ce7d794d8727026c14e0 /backend
parentd94c9eb68e65d53f09bf3dd26ec4d61d245882ad (diff)
downloadiosdc-japan-2025-albatross-3b13a61123becc63823ab0c0941aaff2048b020e.tar.gz
iosdc-japan-2025-albatross-3b13a61123becc63823ab0c0941aaff2048b020e.tar.zst
iosdc-japan-2025-albatross-3b13a61123becc63823ab0c0941aaff2048b020e.zip
feat(backend/worker): calculate code hash in api-server
Diffstat (limited to 'backend')
-rw-r--r--backend/game/hub.go15
-rw-r--r--backend/taskqueue/processor.go15
-rw-r--r--backend/taskqueue/queue.go12
-rw-r--r--backend/taskqueue/tasks.go69
4 files changed, 69 insertions, 42 deletions
diff --git a/backend/game/hub.go b/backend/game/hub.go
index ac71152..aa1b9f2 100644
--- a/backend/game/hub.go
+++ b/backend/game/hub.go
@@ -2,7 +2,9 @@ package game
import (
"context"
+ "crypto/md5"
"errors"
+ "fmt"
"log"
"strings"
"time"
@@ -163,11 +165,13 @@ func (hub *gameHub) run() {
log.Printf("submit: %v", message.message)
code := msg.Data.Code
codeSize := len(code) // TODO: exclude whitespaces.
+ codeHash := calcHash(code)
if err := hub.taskQueue.EnqueueTaskCreateSubmissionRecord(
hub.game.gameID,
message.client.playerID,
code,
codeSize,
+ taskqueue.MD5HexHash(codeHash),
); err != nil {
// TODO: notify failure to player
log.Fatalf("failed to enqueue task: %v", err)
@@ -329,7 +333,8 @@ func (hub *gameHub) processTaskResultCreateSubmissionRecord(
if err := hub.taskQueue.EnqueueTaskCompileSwiftToWasm(
taskResult.TaskPayload.GameID(),
taskResult.TaskPayload.UserID(),
- taskResult.TaskPayload.Code(),
+ taskResult.TaskPayload.Code,
+ taskResult.TaskPayload.CodeHash(),
taskResult.SubmissionID,
); err != nil {
return &codeSubmissionError{
@@ -371,7 +376,7 @@ func (hub *gameHub) processTaskResultCompileSwiftToWasm(
if err := hub.taskQueue.EnqueueTaskCompileWasmToNativeExecutable(
taskResult.TaskPayload.GameID(),
taskResult.TaskPayload.UserID(),
- taskResult.TaskPayload.Code(),
+ taskResult.TaskPayload.CodeHash(),
taskResult.TaskPayload.SubmissionID,
); err != nil {
return &codeSubmissionError{
@@ -429,7 +434,7 @@ func (hub *gameHub) processTaskResultCompileWasmToNativeExecutable(
if err := hub.taskQueue.EnqueueTaskRunTestcase(
taskResult.TaskPayload.GameID(),
taskResult.TaskPayload.UserID(),
- taskResult.TaskPayload.Code(),
+ taskResult.TaskPayload.CodeHash(),
taskResult.TaskPayload.SubmissionID,
int(testcase.TestcaseID),
testcase.Stdin,
@@ -644,3 +649,7 @@ func isTestcaseResultCorrect(expectedStdout, actualStdout string) bool {
actualStdout = strings.TrimSpace(actualStdout)
return actualStdout == expectedStdout
}
+
+func calcHash(code string) string {
+ return fmt.Sprintf("%x", md5.Sum([]byte(code)))
+}
diff --git a/backend/taskqueue/processor.go b/backend/taskqueue/processor.go
index 149ab67..5678cc8 100644
--- a/backend/taskqueue/processor.go
+++ b/backend/taskqueue/processor.go
@@ -29,8 +29,9 @@ func (p *processor) doProcessTaskCreateSubmissionRecord(
submissionID, err := p.q.CreateSubmission(ctx, db.CreateSubmissionParams{
GameID: int32(payload.GameID()),
UserID: int32(payload.UserID()),
- Code: payload.Code(),
+ Code: payload.Code,
CodeSize: int32(payload.CodeSize),
+ CodeHash: string(payload.CodeHash()),
})
if err != nil {
return nil, err
@@ -49,6 +50,7 @@ func (p *processor) doProcessTaskCompileSwiftToWasm(
type swiftcRequestData struct {
MaxDuration int `json:"max_duration_ms"`
Code string `json:"code"`
+ CodeHash string `json:"code_hash"`
}
type swiftcResponseData struct {
Status string `json:"status"`
@@ -57,7 +59,8 @@ func (p *processor) doProcessTaskCompileSwiftToWasm(
}
reqData := swiftcRequestData{
MaxDuration: 5000,
- Code: payload.Code(),
+ Code: payload.Code,
+ CodeHash: string(payload.CodeHash()),
}
reqJSON, err := json.Marshal(reqData)
if err != nil {
@@ -99,7 +102,7 @@ func (p *processor) doProcessTaskCompileWasmToNativeExecutable(
) (*TaskResultCompileWasmToNativeExecutable, error) {
type wasmcRequestData struct {
MaxDuration int `json:"max_duration_ms"`
- Code string `json:"code"`
+ CodeHash string `json:"code_hash"`
}
type wasmcResponseData struct {
Status string `json:"status"`
@@ -108,7 +111,7 @@ func (p *processor) doProcessTaskCompileWasmToNativeExecutable(
}
reqData := wasmcRequestData{
MaxDuration: 5000,
- Code: payload.Code(),
+ CodeHash: string(payload.CodeHash()),
}
reqJSON, err := json.Marshal(reqData)
if err != nil {
@@ -150,7 +153,7 @@ func (p *processor) doProcessTaskRunTestcase(
) (*TaskResultRunTestcase, error) {
type testrunRequestData struct {
MaxDuration int `json:"max_duration_ms"`
- Code string `json:"code"`
+ CodeHash string `json:"code_hash"`
Stdin string `json:"stdin"`
}
type testrunResponseData struct {
@@ -160,7 +163,7 @@ func (p *processor) doProcessTaskRunTestcase(
}
reqData := testrunRequestData{
MaxDuration: 5000,
- Code: payload.Code(),
+ CodeHash: string(payload.CodeHash()),
Stdin: payload.Stdin,
}
reqJSON, err := json.Marshal(reqData)
diff --git a/backend/taskqueue/queue.go b/backend/taskqueue/queue.go
index 515a406..30fe265 100644
--- a/backend/taskqueue/queue.go
+++ b/backend/taskqueue/queue.go
@@ -25,12 +25,14 @@ func (q *Queue) EnqueueTaskCreateSubmissionRecord(
userID int,
code string,
codeSize int,
+ codeHash MD5HexHash,
) error {
task, err := newTaskCreateSubmissionRecord(
gameID,
userID,
code,
codeSize,
+ codeHash,
)
if err != nil {
return err
@@ -43,12 +45,14 @@ func (q *Queue) EnqueueTaskCompileSwiftToWasm(
gameID int,
userID int,
code string,
+ codeHash MD5HexHash,
submissionID int,
) error {
task, err := newTaskCompileSwiftToWasm(
gameID,
userID,
code,
+ codeHash,
submissionID,
)
if err != nil {
@@ -61,13 +65,13 @@ func (q *Queue) EnqueueTaskCompileSwiftToWasm(
func (q *Queue) EnqueueTaskCompileWasmToNativeExecutable(
gameID int,
userID int,
- code string,
+ codeHash MD5HexHash,
submissionID int,
) error {
task, err := newTaskCompileWasmToNativeExecutable(
gameID,
userID,
- code,
+ codeHash,
submissionID,
)
if err != nil {
@@ -80,7 +84,7 @@ func (q *Queue) EnqueueTaskCompileWasmToNativeExecutable(
func (q *Queue) EnqueueTaskRunTestcase(
gameID int,
userID int,
- code string,
+ codeHash MD5HexHash,
submissionID int,
testcaseID int,
stdin string,
@@ -89,7 +93,7 @@ func (q *Queue) EnqueueTaskRunTestcase(
task, err := newTaskRunTestcase(
gameID,
userID,
- code,
+ codeHash,
submissionID,
testcaseID,
stdin,
diff --git a/backend/taskqueue/tasks.go b/backend/taskqueue/tasks.go
index cbe83b1..d5f2993 100644
--- a/backend/taskqueue/tasks.go
+++ b/backend/taskqueue/tasks.go
@@ -8,6 +8,9 @@ import (
type TaskType string
+// MD5 hash in hexadecimal format
+type MD5HexHash string
+
const (
TaskTypeCreateSubmissionRecord TaskType = "create_submission_record"
TaskTypeCompileSwiftToWasm TaskType = "compile_swift_to_wasm"
@@ -16,13 +19,14 @@ const (
)
type TaskPayloadBase struct {
- GameID int
- UserID int
- Code string
+ GameID int
+ UserID int
+ CodeHash MD5HexHash
}
type TaskPayloadCreateSubmissionRecord struct {
TaskPayloadBase
+ Code string
CodeSize int
}
@@ -31,13 +35,15 @@ func newTaskCreateSubmissionRecord(
userID int,
code string,
codeSize int,
+ codeHash MD5HexHash,
) (*asynq.Task, error) {
payload, err := json.Marshal(TaskPayloadCreateSubmissionRecord{
TaskPayloadBase: TaskPayloadBase{
- GameID: gameID,
- UserID: userID,
- Code: code,
+ GameID: gameID,
+ UserID: userID,
+ CodeHash: codeHash,
},
+ Code: code,
CodeSize: codeSize,
})
if err != nil {
@@ -46,28 +52,31 @@ func newTaskCreateSubmissionRecord(
return asynq.NewTask(string(TaskTypeCreateSubmissionRecord), payload), nil
}
-func (t *TaskPayloadCreateSubmissionRecord) GameID() int { return t.TaskPayloadBase.GameID }
-func (t *TaskPayloadCreateSubmissionRecord) UserID() int { return t.TaskPayloadBase.UserID }
-func (t *TaskPayloadCreateSubmissionRecord) Code() string { return t.TaskPayloadBase.Code }
+func (t *TaskPayloadCreateSubmissionRecord) GameID() int { return t.TaskPayloadBase.GameID }
+func (t *TaskPayloadCreateSubmissionRecord) UserID() int { return t.TaskPayloadBase.UserID }
+func (t *TaskPayloadCreateSubmissionRecord) CodeHash() MD5HexHash { return t.TaskPayloadBase.CodeHash }
type TaskPayloadCompileSwiftToWasm struct {
TaskPayloadBase
SubmissionID int
+ Code string
}
func newTaskCompileSwiftToWasm(
gameID int,
userID int,
code string,
+ codeHash MD5HexHash,
submissionID int,
) (*asynq.Task, error) {
payload, err := json.Marshal(TaskPayloadCompileSwiftToWasm{
TaskPayloadBase: TaskPayloadBase{
- GameID: gameID,
- UserID: userID,
- Code: code,
+ GameID: gameID,
+ UserID: userID,
+ CodeHash: codeHash,
},
SubmissionID: submissionID,
+ Code: code,
})
if err != nil {
return nil, err
@@ -75,9 +84,9 @@ func newTaskCompileSwiftToWasm(
return asynq.NewTask(string(TaskTypeCompileSwiftToWasm), payload), nil
}
-func (t *TaskPayloadCompileSwiftToWasm) GameID() int { return t.TaskPayloadBase.GameID }
-func (t *TaskPayloadCompileSwiftToWasm) UserID() int { return t.TaskPayloadBase.UserID }
-func (t *TaskPayloadCompileSwiftToWasm) Code() string { return t.TaskPayloadBase.Code }
+func (t *TaskPayloadCompileSwiftToWasm) GameID() int { return t.TaskPayloadBase.GameID }
+func (t *TaskPayloadCompileSwiftToWasm) UserID() int { return t.TaskPayloadBase.UserID }
+func (t *TaskPayloadCompileSwiftToWasm) CodeHash() MD5HexHash { return t.TaskPayloadBase.CodeHash }
type TaskPayloadCompileWasmToNativeExecutable struct {
TaskPayloadBase
@@ -87,14 +96,14 @@ type TaskPayloadCompileWasmToNativeExecutable struct {
func newTaskCompileWasmToNativeExecutable(
gameID int,
userID int,
- code string,
+ codeHash MD5HexHash,
submissionID int,
) (*asynq.Task, error) {
payload, err := json.Marshal(TaskPayloadCompileWasmToNativeExecutable{
TaskPayloadBase: TaskPayloadBase{
- GameID: gameID,
- UserID: userID,
- Code: code,
+ GameID: gameID,
+ UserID: userID,
+ CodeHash: codeHash,
},
SubmissionID: submissionID,
})
@@ -104,9 +113,11 @@ func newTaskCompileWasmToNativeExecutable(
return asynq.NewTask(string(TaskTypeCompileWasmToNativeExecutable), payload), nil
}
-func (t *TaskPayloadCompileWasmToNativeExecutable) GameID() int { return t.TaskPayloadBase.GameID }
-func (t *TaskPayloadCompileWasmToNativeExecutable) UserID() int { return t.TaskPayloadBase.UserID }
-func (t *TaskPayloadCompileWasmToNativeExecutable) Code() string { return t.TaskPayloadBase.Code }
+func (t *TaskPayloadCompileWasmToNativeExecutable) GameID() int { return t.TaskPayloadBase.GameID }
+func (t *TaskPayloadCompileWasmToNativeExecutable) UserID() int { return t.TaskPayloadBase.UserID }
+func (t *TaskPayloadCompileWasmToNativeExecutable) CodeHash() MD5HexHash {
+ return t.TaskPayloadBase.CodeHash
+}
type TaskPayloadRunTestcase struct {
TaskPayloadBase
@@ -119,7 +130,7 @@ type TaskPayloadRunTestcase struct {
func newTaskRunTestcase(
gameID int,
userID int,
- code string,
+ codeHash MD5HexHash,
submissionID int,
testcaseID int,
stdin string,
@@ -127,9 +138,9 @@ func newTaskRunTestcase(
) (*asynq.Task, error) {
payload, err := json.Marshal(TaskPayloadRunTestcase{
TaskPayloadBase: TaskPayloadBase{
- GameID: gameID,
- UserID: userID,
- Code: code,
+ GameID: gameID,
+ UserID: userID,
+ CodeHash: codeHash,
},
SubmissionID: submissionID,
TestcaseID: testcaseID,
@@ -142,9 +153,9 @@ func newTaskRunTestcase(
return asynq.NewTask(string(TaskTypeRunTestcase), payload), nil
}
-func (t *TaskPayloadRunTestcase) GameID() int { return t.TaskPayloadBase.GameID }
-func (t *TaskPayloadRunTestcase) UserID() int { return t.TaskPayloadBase.UserID }
-func (t *TaskPayloadRunTestcase) Code() string { return t.TaskPayloadBase.Code }
+func (t *TaskPayloadRunTestcase) GameID() int { return t.TaskPayloadBase.GameID }
+func (t *TaskPayloadRunTestcase) UserID() int { return t.TaskPayloadBase.UserID }
+func (t *TaskPayloadRunTestcase) CodeHash() MD5HexHash { return t.TaskPayloadBase.CodeHash }
type TaskResult interface {
Type() TaskType