Skip to content

Admclamb/finish creating submission and sending it to judge0#100

Open
admclamb wants to merge 4 commits into
masterfrom
admclamb/finish-creating-submission-and-sending-it-to-judge0
Open

Admclamb/finish creating submission and sending it to judge0#100
admclamb wants to merge 4 commits into
masterfrom
admclamb/finish-creating-submission-and-sending-it-to-judge0

Conversation

@admclamb

Copy link
Copy Markdown
Contributor

No description provided.

public int AttemptCountForCurrentStep()
=> CurrentStepId is null
? 0
: _attempts.Count(a => a.PipelineStepId == CurrentStepId.Value);
Status = SubmissionJobStatus.Running;

int attemptNumber = _attempts
.Count(a => a.PipelineStepId == CurrentStepId.Value) + 1;
Comment on lines +75 to +104
foreach (var pollResult in pollResults)
{
if (pollResult.TestCaseId == Guid.Empty)
continue;

SubmissionResultStatus status = MapEngineStatus(pollResult.Status);

if (status == SubmissionResultStatus.Accepted &&
testCases.TryGetValue(pollResult.TestCaseId, out TestCase? testCase))
{
string? expected = testCase.ExpectedOutputs
.OrderBy(e => e.Id)
.Select(e => e.Value)
.FirstOrDefault();

string? actual = pollResult.Stdout?.TrimEnd('\n', '\r', ' ');

status = Evaluate(actual, expected, assertConfig);
}

submission.UpdateResult(
testCaseId: pollResult.TestCaseId,
status: status,
runtime: pollResult.RuntimeMs,
memoryUsed: pollResult.MemoryUsedKb,
actualOutput: pollResult.Stdout,
standardOutput: pollResult.Stdout,
standardError: pollResult.Stderr,
compileOutput: pollResult.CompileOutput);
}
Comment on lines +42 to +45
catch
{
return new StepHandlerResult(Succeeded: false, Error: "Could not deserialize token map from execute step.");
}
Comment on lines +57 to +60
catch (Exception ex)
{
return new StepHandlerResult(Succeeded: false, Error: $"Judge0 poll failed: {ex.Message}");
}
Comment on lines +47 to +50
catch
{
return Fail("Could not deserialize poll results.");
}
Comment on lines +117 to +120
catch (Exception ex)
{
return Fail($"Could not complete submission: {ex.Message}");
}
Comment on lines +165 to +168
catch
{
return value.Trim();
}
Comment on lines +20 to +24
catch (Exception ex)
{
LogFailed(ex);
throw new JobExecutionException(ex, refireImmediately: false);
}

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a full “submission pipeline” execution path: creating a SubmissionJob alongside a Submission, seeding/configuring an execution pipeline, and processing jobs via RabbitMQ-triggered execution with a Quartz fallback. It adds domain models for pipelines/jobs, infrastructure persistence/migrations, and a Judge0-based execution engine with language-specific code templating.

Changes:

  • Add domain + EF persistence for ExecutionPipeline / SubmissionJob (including migrations and seeders).
  • Add Judge0 execution engine strategy, step handlers, and code template strategies (JS/TS/Python).
  • Add API endpoint/service for creating submissions and wire job processing via RabbitMQ + Quartz.

Reviewed changes

Copilot reviewed 64 out of 65 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
PLAN.md High-level pipeline design plan
Directory.Packages.props Add Microsoft.Extensions.Http package version
Algowars.Infrastructure/Repositories/TestSuiteWriteRepository.cs Add pipeline-id lookup for setups
Algowars.Infrastructure/Repositories/SubmissionJobRepository.cs Add job persistence + attempt insert
Algowars.Infrastructure/Repositories/ExecutionPipelineRepository.cs Add pipeline persistence methods
Algowars.Infrastructure/Persistence/Seeders/Problems/TwoSumProblemSeeder.cs Seed setups with pipeline_id
Algowars.Infrastructure/Persistence/Seeders/Problems/HelloOrGoodbyeProblemSeeder.cs Seed setups with pipeline_id
Algowars.Infrastructure/Persistence/Seeders/Judge0PipelineSeeder.cs Seed default Judge0 pipeline/steps
Algowars.Infrastructure/Persistence/Seeders/DemoDataSeeder.cs Seed demo setups with pipeline_id
Algowars.Infrastructure/Persistence/Configuration/SubmissionJobConfiguration.cs Map submission_jobs + attempts
Algowars.Infrastructure/Persistence/Configuration/ProblemSetupConfiguration.cs Map problem_setups.pipeline_id
Algowars.Infrastructure/Persistence/Configuration/Judge0StepConfigurationConfiguration.cs Map judge0 step config table
Algowars.Infrastructure/Persistence/Configuration/ExecutionPipelineConfiguration.cs Map pipelines + pipeline steps
Algowars.Infrastructure/Persistence/Configuration/AssertStepConfigurationConfiguration.cs Map assert step config table
Algowars.Infrastructure/Persistence/AlgoWarsDbContext.cs Add DbSets for new entities
Algowars.Infrastructure/Migrations/AlgoWarsDbContextModelSnapshot.cs Update EF snapshot
Algowars.Infrastructure/Migrations/20260712054551_AddSubmissionPipeline.Designer.cs Add migration designer output
Algowars.Infrastructure/Migrations/20260712054551_AddSubmissionPipeline.cs Create new tables + add pipeline_id
Algowars.Infrastructure/Messaging/Consumers/RabbitMqConsumerService.cs Trigger processor on submission-created
Algowars.Infrastructure/Jobs/Submissions/SubmissionJobProcessorService.cs Orchestrate step execution per job
Algowars.Infrastructure/Jobs/Submissions/SubmissionJobProcessorJob.cs Quartz job to process pending jobs
Algowars.Infrastructure/Jobs/Submissions/SubmissionCleanupService.cs Mark stale jobs failed
Algowars.Infrastructure/InfrastructureServiceRegistration.cs Register execution engine, repos, jobs
Algowars.Infrastructure/ExecutionEngine/StepHandlers/StepHandlerRegistry.cs Resolve handler by step type
Algowars.Infrastructure/ExecutionEngine/StepHandlers/Judge0PollStepHandler.cs Poll Judge0 tokens/results
Algowars.Infrastructure/ExecutionEngine/StepHandlers/Judge0ExecuteStepHandler.cs Render + submit batch to Judge0
Algowars.Infrastructure/ExecutionEngine/StepHandlers/EvaluateStepHandler.cs Evaluate outputs and update results
Algowars.Infrastructure/ExecutionEngine/Judge0/Judge0StepConfiguration.cs Judge0 step config POCO
Algowars.Infrastructure/ExecutionEngine/Judge0/Judge0ExecutionEngineStrategy.cs Judge0 HTTP submit/poll implementation
Algowars.Infrastructure/ExecutionEngine/CodeTemplates/TypeScriptCodeTemplateStrategy.cs TS harness renderer
Algowars.Infrastructure/ExecutionEngine/CodeTemplates/PythonCodeTemplateStrategy.cs Python harness renderer
Algowars.Infrastructure/ExecutionEngine/CodeTemplates/JavaScriptCodeTemplateStrategy.cs JS harness renderer
Algowars.Infrastructure/ExecutionEngine/CodeTemplates/CodeTemplateStrategyResolver.cs Resolve template by language
Algowars.Infrastructure/ExecutionEngine/Assert/AssertStepConfiguration.cs Assert strategy config + enum
Algowars.Infrastructure/Algowars.Infrastructure.csproj Add Microsoft.Extensions.Http ref
Algowars.Domain/TestSuites/ITestSuiteWriteRepository.cs Add pipeline-id lookup method
Algowars.Domain/SubmissionJobs/SubmissionJob.cs New SubmissionJob aggregate
Algowars.Domain/SubmissionJobs/ISubmissionJobRepository.cs New job repository interface
Algowars.Domain/SubmissionJobs/Exceptions/SubmissionJobException.cs New domain exception
Algowars.Domain/SubmissionJobs/Enums/SubmissionJobStatus.cs New job status enum
Algowars.Domain/SubmissionJobs/Enums/SubmissionJobAttemptStatus.cs New attempt status enum
Algowars.Domain/SubmissionJobs/Entities/SubmissionJobAttempt.cs New attempt entity
Algowars.Domain/Problems/Entities/ProblemSetup.cs Add PipelineId to setups
Algowars.Domain/Problems/Entities/Problem.cs Require pipelineId when adding setups
Algowars.Domain/ExecutionPipelines/IExecutionPipelineRepository.cs New pipeline repo interface
Algowars.Domain/ExecutionPipelines/ExecutionPipeline.cs New pipeline aggregate
Algowars.Domain/ExecutionPipelines/Enums/ExecutionPipelineStepType.cs New step type enum
Algowars.Domain/ExecutionPipelines/Entities/ExecutionPipelineStep.cs New step entity
Algowars.Domain.Tests/Problem/Entities/ProblemTests.cs Update tests for new AddSetup signature
Algowars.Application/Submissions/Dtos/CreateSubmissionDto.cs DTO for submission creation
Algowars.Application/Services/Submissions/SubmissionService.cs App service wrapper around command
Algowars.Application/ExecutionEngine/IStepHandlerRegistry.cs Execution engine registry interface
Algowars.Application/ExecutionEngine/IStepHandler.cs Step handler interfaces/DTOs
Algowars.Application/ExecutionEngine/IExecutionEngineStrategy.cs Execution engine abstraction
Algowars.Application/ExecutionEngine/ICodeTemplateStrategyResolver.cs Template resolver interface
Algowars.Application/ExecutionEngine/ICodeTemplateStrategy.cs Template strategy interface
Algowars.Application/Configuration/QuartzOptions.cs Add processor job schedule option
Algowars.Application/Configuration/ExecutionEngineOptions.cs Add execution engine options model
Algowars.Application/Commands/Submissions/CreateSubmission/CreateSubmissionHandler.cs Create SubmissionJob + pipeline resolution
Algowars.Application/ApplicationServiceRegistration.cs Register submission service
Algowars.Api/Requests/Submission/CreateSubmissionRequest.cs API request contract
Algowars.Api/Controllers/SubmissionController.cs Add POST submission endpoint
Algowars.Api/appsettings.json Add ExecutionEngines + Quartz config
Algowars.Api/appsettings.Development.json Dev Judge0 base URL config
Algowars.Api/ApiServiceRegistration.cs Enable enum-as-string JSON serialization
Files not reviewed (1)
  • Algowars.Infrastructure/Migrations/20260712054551_AddSubmissionPipeline.Designer.cs: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

using Algowars.Infrastructure.Persistence.Seeders.Problems;

using Algowars.Infrastructure.Repositories;
using Algowars.Infrastructure.Persistence.Seeders.Problems;using Algowars.Infrastructure.Repositories;
Comment on lines +106 to +111
if (opts.Judge0.Enabled)
{
var judge0Opts = opts.Judge0;
services.AddHttpClient(nameof(Judge0ExecutionEngineStrategy), client =>
{
client.BaseAddress = new Uri(judge0Opts.BaseUrl.TrimEnd('/') + "/");
Comment on lines +132 to +135
services.AddScoped<IStepHandler, Judge0ExecuteStepHandler>();
services.AddScoped<IStepHandler, Judge0PollStepHandler>();
services.AddScoped<IStepHandler, EvaluateStepHandler>();
services.AddScoped<IStepHandlerRegistry, StepHandlerRegistry>();
Comment on lines +34 to +35
if (pipelineId is null)
return Result.NotFound($"No pipeline configured for problem setup {request.ProblemSetupId}.");
Comment on lines 52 to +56
await submissionRepository.AddAsync(submission, cancellationToken);

var job = new SubmissionJob(submission.Id, pipeline.Id, firstStep.Id);
await submissionJobRepository.AddAsync(job, cancellationToken);

Comment on lines +22 to +26
process.stdin.on('end', () => {
const _args: unknown[] = _input.trim().split('\n').map((line: string) => JSON.parse(line));
const _result = FUNCTION_NAME_PLACEHOLDER(...(_args as Parameters<typeof FUNCTION_NAME_PLACEHOLDER>));
console.log(JSON.stringify(_result));
});
Comment on lines +23 to +27
def _main():
lines = sys.stdin.read().strip().split('\n')
args = [json.loads(line) for line in lines]
result = FUNCTION_NAME_PLACEHOLDER(*args)
print(json.dumps(result))
Comment on lines +139 to +146
bool match = config.Strategy switch
{
AssertStrategy.FloatTolerance => TryFloatCompare(actual, expected, config.Tolerance ?? 1e-6m),
AssertStrategy.SetEquality => NormalizeJson(actual) == NormalizeJson(expected),
_ => config.CaseSensitive
? actual.Trim() == expected.Trim()
: string.Equals(actual.Trim(), expected.Trim(), StringComparison.OrdinalIgnoreCase)
};
Comment on lines 6 to +10
public interface ITestSuiteWriteRepository : IRepository<TestSuite>
{
Task<IReadOnlyList<Guid>> FindTestCaseIdsByProblemSetupIdAsync(Guid problemSetupId, CancellationToken cancellationToken = default);
} No newline at end of file
Task<Guid?> FindPipelineIdByProblemSetupIdAsync(Guid problemSetupId, CancellationToken cancellationToken = default);
}
Comment on lines +43 to +52
public async Task<Guid?> FindPipelineIdByProblemSetupIdAsync(
Guid problemSetupId,
CancellationToken cancellationToken = default)
{
return await context.Problems
.AsNoTracking()
.SelectMany(p => p.Setups)
.Where(s => s.Id == problemSetupId)
.Select(s => (Guid?)s.PipelineId)
.FirstOrDefaultAsync(cancellationToken);
Comment on lines +105 to +108
catch (Exception ex)
{
return Fail($"Judge0 batch submit failed: {ex.Message}");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants