feat: #6 [3] Add LimitedWriter and move file related utils out from package utils

This commit is contained in:
Paul Pan 2024-01-06 16:06:16 +08:00
parent 8e3222daab
commit 31391f6ce0
Signed by: Paul
GPG Key ID: D639BDF5BA578AF4
9 changed files with 47 additions and 21 deletions

View File

@ -7,6 +7,7 @@ import (
"git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/e"
"git.0x7f.app/WOJ/woj-server/internal/model" "git.0x7f.app/WOJ/woj-server/internal/model"
"git.0x7f.app/WOJ/woj-server/internal/service/runner" "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" "git.0x7f.app/WOJ/woj-server/pkg/utils"
"github.com/hibiken/asynq" "github.com/hibiken/asynq"
"go.uber.org/zap" "go.uber.org/zap"
@ -28,10 +29,10 @@ func (h *handler) Judge(_ context.Context, t *asynq.Task) error {
// 1. write user code // 1. write user code
userCode := filepath.Join(runner.UserDir, user, fmt.Sprintf("%s.%s", user, p.Submission.Language)) userCode := filepath.Join(runner.UserDir, user, fmt.Sprintf("%s.%s", user, p.Submission.Language))
if !utils.FileTouch(userCode) { if !file.FileTouch(userCode) {
return e.InternalError, 0, systemError return e.InternalError, 0, systemError
} }
err := utils.FileWrite(userCode, []byte(p.Submission.Code)) err := file.FileWrite(userCode, []byte(p.Submission.Code))
if err != nil { if err != nil {
return e.InternalError, 0, systemError return e.InternalError, 0, systemError
} }

View File

@ -2,7 +2,7 @@ package config
import ( import (
"git.0x7f.app/WOJ/woj-server/internal/model" "git.0x7f.app/WOJ/woj-server/internal/model"
"git.0x7f.app/WOJ/woj-server/pkg/utils" "git.0x7f.app/WOJ/woj-server/pkg/file"
"github.com/samber/do" "github.com/samber/do"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@ -19,7 +19,7 @@ type Service interface {
func NewService(i *do.Injector) (Service, error) { func NewService(i *do.Injector) (Service, error) {
cliCtx := do.MustInvoke[*cli.Context](i) cliCtx := do.MustInvoke[*cli.Context](i)
data, err := utils.FileRead(cliCtx.String("config")) data, err := file.FileRead(cliCtx.String("config"))
if err != nil { if err != nil {
log.Printf("Failed to setup config: %s\n", err.Error()) log.Printf("Failed to setup config: %s\n", err.Error())
return nil, err return nil, err

View File

@ -3,7 +3,7 @@ package runner
import ( import (
"fmt" "fmt"
"git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/e"
"git.0x7f.app/WOJ/woj-server/pkg/utils" "git.0x7f.app/WOJ/woj-server/pkg/file"
"go.uber.org/zap" "go.uber.org/zap"
"os" "os"
"os/exec" "os/exec"
@ -69,10 +69,10 @@ func (s *service) checkAndExecute(version uint, user string, lang string, script
func (s *service) ProblemExists(version uint) bool { func (s *service) ProblemExists(version uint) bool {
problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version)) problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version))
return utils.FileExist(problemPath) return file.FileExist(problemPath)
} }
func (s *service) userExists(user string, file string) bool { func (s *service) userExists(user string, name string) bool {
userPath := filepath.Join(UserDir, user, file) userPath := filepath.Join(UserDir, user, name)
return utils.FileExist(userPath) return file.FileExist(userPath)
} }

View File

@ -3,6 +3,7 @@ package runner
import ( import (
"fmt" "fmt"
"git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/e"
"git.0x7f.app/WOJ/woj-server/pkg/file"
"git.0x7f.app/WOJ/woj-server/pkg/utils" "git.0x7f.app/WOJ/woj-server/pkg/utils"
"os" "os"
"path/filepath" "path/filepath"
@ -15,11 +16,11 @@ func (s *service) Compile(version uint, user string, lang string) (JudgeStatus,
status := s.checkAndExecute(version, user, lang, "problem_compile.sh", e.RunnerUserCompileFailed) status := s.checkAndExecute(version, user, lang, "problem_compile.sh", e.RunnerUserCompileFailed)
log := filepath.Join(UserDir, user, fmt.Sprintf("%s.compile.log", user)) log := filepath.Join(UserDir, user, fmt.Sprintf("%s.compile.log", user))
msg, err := utils.FileRead(log) msg, err := file.FileRead(log)
msg = utils.If(err == nil, msg, nil) msg = utils.If(err == nil, msg, nil)
msgText := string(msg) msgText := string(msg)
if !utils.FileExist(target) || utils.FileEmpty(target) { if !file.FileExist(target) || file.FileEmpty(target) {
return JudgeStatus{ return JudgeStatus{
Message: "compile failed", Message: "compile failed",
Tasks: []TaskStatus{{Verdict: VerdictCompileError, Message: msgText}}}, Tasks: []TaskStatus{{Verdict: VerdictCompileError, Message: msgText}}},

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/e"
"git.0x7f.app/WOJ/woj-server/pkg/file"
"git.0x7f.app/WOJ/woj-server/pkg/utils" "git.0x7f.app/WOJ/woj-server/pkg/utils"
"go.uber.org/zap" "go.uber.org/zap"
"os" "os"
@ -20,7 +21,7 @@ func (s *service) loadImage(cfg *depConfig) e.Status {
err := utils.NewTryErr(). err := utils.NewTryErr().
Try(func() error { Try(func() error {
// import from tarball // import from tarball
if !utils.FileExist(cfg.tarball) { if !file.FileExist(cfg.tarball) {
return errors.New("tarball not exists") return errors.New("tarball not exists")
} }
return s.execute("bash", "-c", fmt.Sprintf("gzip -d -c %s | podman load", cfg.tarball)) return s.execute("bash", "-c", fmt.Sprintf("gzip -d -c %s | podman load", cfg.tarball))
@ -31,7 +32,7 @@ func (s *service) loadImage(cfg *depConfig) e.Status {
}). }).
Or(func() error { Or(func() error {
// build from dockerfile // build from dockerfile
if !utils.FileExist(cfg.dockerfile) { if !file.FileExist(cfg.dockerfile) {
return errors.New("dockerfile not exists") return errors.New("dockerfile not exists")
} }
return s.execute("podman", "build", "-f", cfg.dockerfile, "-t", cfg.image, ".") return s.execute("podman", "build", "-f", cfg.dockerfile, "-t", cfg.image, ".")
@ -52,7 +53,7 @@ func (s *service) EnsureDeps(force bool) e.Status {
// check mark // check mark
if force { if force {
_ = os.Remove(mark) _ = os.Remove(mark)
} else if utils.FileExist(mark) { } else if file.FileExist(mark) {
return e.Success return e.Success
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/e"
"git.0x7f.app/WOJ/woj-server/pkg/down" "git.0x7f.app/WOJ/woj-server/pkg/down"
"git.0x7f.app/WOJ/woj-server/pkg/file"
"git.0x7f.app/WOJ/woj-server/pkg/unzip" "git.0x7f.app/WOJ/woj-server/pkg/unzip"
"git.0x7f.app/WOJ/woj-server/pkg/utils" "git.0x7f.app/WOJ/woj-server/pkg/utils"
"go.uber.org/zap" "go.uber.org/zap"
@ -38,7 +39,7 @@ func (s *service) prebuild(version uint, force bool) e.Status {
mark := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), ".mark.prebuild") mark := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), ".mark.prebuild")
if force { if force {
_ = os.Remove(mark) _ = os.Remove(mark)
} else if utils.FileExist(mark) { } else if file.FileExist(mark) {
return e.Success return e.Success
} }

View File

@ -5,7 +5,7 @@ import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"git.0x7f.app/WOJ/woj-server/pkg/utils" "git.0x7f.app/WOJ/woj-server/pkg/file"
"golang.org/x/text/encoding/charmap" "golang.org/x/text/encoding/charmap"
"io" "io"
"path/filepath" "path/filepath"
@ -57,7 +57,7 @@ func (t *TaskStatus) getInfoText(infoFile string) *TaskStatus {
} }
var err error var err error
t.infoText, err = utils.FileRead(infoFile) t.infoText, err = file.FileRead(infoFile)
if err != nil { if err != nil {
t.Verdict = VerdictSystemError t.Verdict = VerdictSystemError
t.Message = "cannot read info file" t.Message = "cannot read info file"
@ -128,7 +128,7 @@ func (t *TaskStatus) getJudgeText(judgeFile string) *TaskStatus {
return t return t
} }
j, err := utils.FileRead(judgeFile) j, err := file.FileRead(judgeFile)
if err != nil { if err != nil {
t.Verdict = VerdictSystemError t.Verdict = VerdictSystemError
t.Message = "cannot read judge file" t.Message = "cannot read judge file"

View File

@ -1,6 +1,7 @@
package utils package file
import ( import (
"git.0x7f.app/WOJ/woj-server/pkg/utils"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
@ -20,7 +21,7 @@ func FileWrite(filePath string, content []byte) error {
func FileExist(filePath string) bool { func FileExist(filePath string) bool {
_, err := os.Stat(filePath) _, err := os.Stat(filePath)
return If(err == nil || os.IsExist(err), true, false) return utils.If(err == nil || os.IsExist(err), true, false)
} }
func FileEmpty(filePath string) bool { func FileEmpty(filePath string) bool {
@ -35,5 +36,5 @@ func FileTouch(filePath string) bool {
base := filepath.Dir(filePath) base := filepath.Dir(filePath)
_ = os.MkdirAll(base, 0755) _ = os.MkdirAll(base, 0755)
_, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644) _, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
return If(err == nil, true, false) return utils.If(err == nil, true, false)
} }

21
pkg/file/writer.go Normal file
View File

@ -0,0 +1,21 @@
package file
import (
"fmt"
"os"
)
type LimitedWriter struct {
File *os.File
Limit int64
n int64
}
func (lw *LimitedWriter) Write(p []byte) (n int, err error) {
if lw.n+int64(len(p)) > lw.Limit {
return 0, fmt.Errorf("output limit exceeded")
}
n, err = lw.File.Write(p)
lw.n += int64(n)
return
}