Admclamb/finish creating submission and sending it to judge0#100
Open
admclamb wants to merge 4 commits into
Open
Admclamb/finish creating submission and sending it to judge0#100admclamb wants to merge 4 commits into
admclamb wants to merge 4 commits into
Conversation
| 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); | ||
| } |
Contributor
There was a problem hiding this comment.
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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.