How cy-r0x/judgeengine works
1. What this repository is
- This is a Go-based judge engine for judgenot0, not a user-facing app.
- Its job is to receive code submissions, queue them, execute them inside isolate, compare output, and report verdicts back to the main system.
2. Top-level process shape
- The binary appears to support multiple runtime modes through cmd/:
- worker/runtime execution,
- HTTP serving/health endpoints,
- submission handling,
- node registration,
- routes and metrics.
- That suggests one deployable engine with multiple operational entrypoints rather than separate services.
3. Configuration boundary
- config/ centralizes runtime configuration, likely from environment variables as described in the README.
- Important settings are RabbitMQ connection details, queue name, worker count, HTTP port, engine secret key, and the server webhook endpoint.
- This config layer is the main boundary between deployment/environment and the engine logic.
4. Messaging and async job flow
- queue/ is the RabbitMQ integration layer.
- The engine consumes submission jobs asynchronously from a queue, which decouples the front-end/API server from execution latency.
- queue/connection.go, publisher.go, consumer.go, and amqp.go indicate explicit broker connection management plus separate publish/consume paths.
5. Scheduling and concurrency
- scheduler/ likely coordinates workers and submission execution concurrency.
- The README’s WORKER_COUNT maps directly to a parallel worker pool model, where each worker runs an isolated sandboxed job.
- This is the engine’s main internal throughput control point.
6. Execution pipeline
- handlers/ contains the submission lifecycle logic:
- parsing metadata,
- compiling/running code,
- comparing output,
- producing verdicts.
- The flow is likely: decode submission metadata → select language handler → compile if needed → run in isolate → compare output → assemble verdict.
- handlers/types.go, submission.go, and verdict.go suggest this package owns the core domain objects used during evaluation.
7. Language-specific execution adapters
- languages/ contains the per-language execution definitions for C, C++, Python, and Node.js.
- This package is the main polymorphic boundary in the engine: it abstracts compile/run commands, file naming, and runtime requirements per language.
- C and C++ are compile-to-binary flows; Python and Node.js are interpreted flows.
8. Sandboxing and host dependencies
- The architecture depends on Linux-only isolate for security and resource limits.
- Actual execution is constrained by host-level capabilities: namespaces, cgroups, and installed compilers/runtimes (gcc, g++, python3, node/nodejs).
- This means execution is intentionally split between Go orchestration and OS-level sandboxing.
9. Verdict and comparison logic
- handlers/compare.go and compare_float.go indicate two output comparison modes:
- strict comparison,
- tolerant floating-point comparison.
- handlers/verdict.go likely normalizes execution results into the engine’s verdict model before reporting upstream.
- This is a key correctness boundary separate from raw process execution.
10. Integration back to the main server
- The engine does not appear to own the full judging system; it reports results to an external server.
- The README’s SERVER_ENDPOINT and ENGINE_KEY suggest authenticated webhook callbacks to a central API after each verdict.
- So the data flow is: main server enqueues submission → engine consumes and judges → engine posts verdict back to main server.
11. HTTP and observability
- cmd/serve.go, cmd/routes.go, and cmd/prom.go indicate lightweight HTTP endpoints for operational use.
- These are likely for health checks, internal debugging, and Prometheus-style metrics rather than user traffic.
- That makes HTTP a side channel for observability, while RabbitMQ is the primary work transport.
12. Core domain models
- structs/ contains the shared data contracts:
- submission,
- verdict,
- worker.
- These structs likely travel across the queue, scheduler, handlers, and webhook boundary, so they define the stable internal schema of the engine.
13. Utility layer
- utils/sendResponse.go suggests a small support layer for HTTP responses or internal API responses.
- This is peripheral compared to the queue/execution pipeline, but it helps indicate the repo also exposes some service endpoints, not just background workers.
14. Architecture summary for a diagram
- The main diagram should show:
- external API/server submitting jobs,
- RabbitMQ as the async buffer,
- Go engine workers/scheduler as consumers,
- languages + handlers as execution/comparison logic,
- isolate plus host compilers/runtimes as the execution substrate,
- webhook callback back to the main server,
- optional HTTP/metrics endpoints for operations.
Main entry points: handler.go Submission flow · scheduler.go Scheduler · config.go Config · c.go Languages
Components 23
External systems
Outside services and host-level dependencies the engine relies on.
- Main server · Upstream system that enqueues submissions and receives verdict callbacks.
- RabbitMQ · Asynchronous queue that buffers submission jobs between server and workers.
- isolate · Linux sandbox used to run submissions with resource limits and isolation.
- Host runtimes · Installed language toolchain used by language adapters to compile or execute code.
Judge engine
Core packages inside this repository that move submissions through judging.
- Config · Centralized environment-driven settings for broker, workers, HTTP, and webhook access.
config/config.go - Queue layer · RabbitMQ connection, publishing, and consuming logic.
queue/amqp.go - Scheduler · Coordinates worker concurrency and submission execution throughput.
scheduler/scheduler.go - Submission flow · Owns submission parsing, execution orchestration, and verdict assembly.
handlers/handler.go - Meta parse · Extracts submission metadata and selects the execution path.
handlers/parse_meta.go - Compare · Performs strict output comparison and floating-point tolerant comparison.
handlers/compare.go - Verdicts · Normalizes execution outcomes into verdicts reported upstream.
handlers/verdict.go - Languages · Per-language compile and run definitions for supported submissions.
languages/c.go - C / C++ · Adapters for compiled languages that build a binary before execution.
languages/cpp.go - Python / Node · Adapters for interpreted runtimes executed directly by the sandbox.
languages/python.go - Submission · Shared submission data contract passed across queue, scheduler, and handlers.
structs/submission.go - Verdict model · Shared verdict data contract used to report results back to the main server.
structs/verdict.go - Worker model · Worker state and identity used by the scheduler and runtime orchestration.
structs/worker.go
Ops entrypoints
HTTP and process entrypoints used to run or observe the engine.
- Run worker · Starts the worker/runtime execution mode.
cmd/run.go - HTTP serve · Starts lightweight HTTP service endpoints for operations.
cmd/serve.go - Metrics · Exposes Prometheus-style operational metrics.
cmd/prom.go - Routes · Registers HTTP routes for health and support endpoints.
cmd/routes.go - Submit mode · Handles submission-related process mode and wiring.
cmd/submit.go - Register node · Registers the engine node with the main system.
cmd/register_node.go
Connections 24
- Main server → RabbitMQ: enqueue · The upstream system places submissions onto the broker.
- RabbitMQ → Queue layer: consume/publish · The engine connects to the broker through its AMQP layer.
- Config → Queue layer: broker settings · Queue connection and queue names are configured centrally.
- Config → Scheduler: worker count · Runtime concurrency is driven by environment configuration.
- Config → Submission flow: engine settings · Handler behavior depends on shared runtime settings and secrets.
- Scheduler → Submission flow: dispatch · The scheduler sends jobs into the judging pipeline.
- Submission flow → Meta parse: parse · Submission metadata is decoded before execution starts.
- Meta parse → Languages: select adapter · Parsed metadata determines which language adapter runs.
- Languages → C / C++: compiled languages · C and C++ use compile-then-run adapter logic.
- Languages → Python / Node: interpreted languages · Python and Node.js use direct execution adapter logic.
- C / C++ → Host runtimes: compile · Compiled language adapters depend on host compilers.
- Python / Node → Host runtimes: execute · Interpreted runtimes depend on installed host interpreters.
- Submission flow → isolate: sandbox run · Execution happens inside the isolate sandbox.
- Submission flow → Compare: check output · Produced output is compared against expected results.
- Compare → Verdicts: normalize · Comparison results are converted into verdict objects.
- Submission flow → Verdict model: build verdict · The pipeline assembles the final verdict contract.
- Verdicts → Main server: callback · Final verdicts are posted back to the main system.
- Worker model → Scheduler: coordination · Worker state is managed as part of scheduling.
- Submission → Submission flow: input schema · Submission records flow through the judging pipeline.
- Run worker → Scheduler: start workers · Worker entrypoint boots the scheduling and execution loop.
- HTTP serve → Routes: wire routes · HTTP service loads route definitions.
- HTTP serve → Metrics: expose metrics · Operational metrics are served alongside HTTP endpoints.
- Register node → Main server: register node · Node registration reaches the upstream system.
- Submit mode → Queue layer: submit job · Submission mode can publish work into the broker.