RYP / backend /compiler /executor /executor.go
Soumya79's picture
Upload 1361 files
f91a684 verified
package executor
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"RYP/backend/compiler/models"
"RYP/backend/compiler/sandbox"
)
const (
defaultPythonImage = "python-runner:latest"
defaultCppImage = "cpp-runner:latest"
defaultJavaImage = "java-runner:latest"
)
// Execute runs the code in the specified language using Docker sandboxing.
func Execute(req models.RunRequest) (*models.ExecutionResult, error) {
// Create temporary directory for this execution
tmpDir, err := os.MkdirTemp("", "ryp_sandbox_*")
if err != nil {
return nil, fmt.Errorf("failed to create temp directory: %w", err)
}
// Defer cleanup of the temporary directory
defer os.RemoveAll(tmpDir)
containerDir := "/sandbox"
ctx := context.Background()
var result *sandbox.ExecutionResult
var execErr error
switch normalizeLanguage(req.Language) {
case "python":
// Write python code to main.py
scriptPath := filepath.Join(tmpDir, "main.py")
if err := os.WriteFile(scriptPath, []byte(req.Code), 0644); err != nil {
return nil, fmt.Errorf("failed to write python file: %w", err)
}
result, execErr = sandbox.RunWithDocker(
ctx,
runnerImage("RYP_PYTHON_IMAGE", defaultPythonImage),
tmpDir,
containerDir,
3*time.Second,
[]string{"python", "main.py"},
req.CustomInput,
)
case "cpp":
// Write C++ code to main.cpp
srcPath := filepath.Join(tmpDir, "main.cpp")
if err := os.WriteFile(srcPath, []byte(req.Code), 0644); err != nil {
return nil, fmt.Errorf("failed to write cpp file: %w", err)
}
// Compile
compResult, err := sandbox.RunWithDocker(
ctx,
runnerImage("RYP_CPP_IMAGE", defaultCppImage),
tmpDir,
containerDir,
5*time.Second,
[]string{"g++", "main.cpp", "-o", "main"},
"",
)
if err != nil {
return nil, fmt.Errorf("compile error: %w", err)
}
if compResult.ExitCode != 0 {
// Compilation failed
return &models.ExecutionResult{
Stdout: compResult.Stdout,
Stderr: compResult.Stderr,
ExitCode: compResult.ExitCode,
DurationMs: compResult.DurationMs,
}, nil
}
// Execute
result, execErr = sandbox.RunWithDocker(
ctx,
runnerImage("RYP_CPP_IMAGE", defaultCppImage),
tmpDir,
containerDir,
3*time.Second,
[]string{"./main"},
req.CustomInput,
)
case "java":
// Write Java code to Main.java
srcPath := filepath.Join(tmpDir, "Main.java")
if err := os.WriteFile(srcPath, []byte(req.Code), 0644); err != nil {
return nil, fmt.Errorf("failed to write java file: %w", err)
}
// Compile
compResult, err := sandbox.RunWithDocker(
ctx,
runnerImage("RYP_JAVA_IMAGE", defaultJavaImage),
tmpDir,
containerDir,
5*time.Second,
[]string{"javac", "Main.java"},
"",
)
if err != nil {
return nil, fmt.Errorf("compile error: %w", err)
}
if compResult.ExitCode != 0 {
// Compilation failed
return &models.ExecutionResult{
Stdout: compResult.Stdout,
Stderr: compResult.Stderr,
ExitCode: compResult.ExitCode,
DurationMs: compResult.DurationMs,
}, nil
}
// Execute
result, execErr = sandbox.RunWithDocker(
ctx,
runnerImage("RYP_JAVA_IMAGE", defaultJavaImage),
tmpDir,
containerDir,
3*time.Second,
[]string{"java", "Main"},
req.CustomInput,
)
default:
return nil, fmt.Errorf("unsupported language: %s", req.Language)
}
if execErr != nil {
return nil, fmt.Errorf("execution failed: %w", execErr)
}
return &models.ExecutionResult{
Stdout: result.Stdout,
Stderr: result.Stderr,
ExitCode: result.ExitCode,
TimeLimitExceeded: result.TimeLimitExceeded,
DurationMs: result.DurationMs,
}, nil
}
func normalizeLanguage(language string) string {
switch strings.ToLower(strings.TrimSpace(language)) {
case "py", "python3":
return "python"
case "c++", "cpp":
return "cpp"
default:
return strings.ToLower(strings.TrimSpace(language))
}
}
func runnerImage(envName, fallback string) string {
value := strings.TrimSpace(os.Getenv(envName))
if value == "" {
return fallback
}
return value
}