From 240a631ececc17d2f5068690d70b3774b519c83b Mon Sep 17 00:00:00 2001 From: Tobias Werth Date: Mon, 1 Sep 2025 18:44:57 +0200 Subject: [PATCH] Properly record start and end times of judging runs. The previously recorded end time was the time when we processed the judging run result server wise which is done asynchronously. Progress towards: https://github.com/DOMjudge/domjudge/issues/1164 --- judge/judgedaemon.main.php | 3 ++ webapp/migrations/Version20250831173317.php | 36 +++++++++++++++++++ .../Controller/API/JudgehostController.php | 11 ++++-- webapp/src/Entity/JudgingRun.php | 21 +++++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 webapp/migrations/Version20250831173317.php diff --git a/judge/judgedaemon.main.php b/judge/judgedaemon.main.php index 314a132f73..636a1aa747 100644 --- a/judge/judgedaemon.main.php +++ b/judge/judgedaemon.main.php @@ -1325,6 +1325,7 @@ function compile( function judge(array $judgeTask): bool { global $EXITCODES, $myhost, $options, $workdirpath, $exitsignalled, $gracefulexitsignalled, $endpointID; + $startTime = microtime(true); $compile_config = dj_json_decode($judgeTask['compile_config']); $run_config = dj_json_decode($judgeTask['run_config']); @@ -1509,6 +1510,8 @@ function judge(array $judgeTask): bool $new_judging_run = [ 'runresult' => urlencode($result), + 'start_time' => urlencode((string)$startTime), + 'end_time' => urlencode((string)microtime(true)), 'runtime' => urlencode((string)$runtime), 'output_run' => rest_encode_file($passdir . '/program.out', $output_storage_limit), 'output_error' => rest_encode_file($passdir . '/program.err', $output_storage_limit), diff --git a/webapp/migrations/Version20250831173317.php b/webapp/migrations/Version20250831173317.php new file mode 100644 index 0000000000..9416554995 --- /dev/null +++ b/webapp/migrations/Version20250831173317.php @@ -0,0 +1,36 @@ +addSql('ALTER TABLE judging_run ADD start_time NUMERIC(32, 9) UNSIGNED DEFAULT NULL COMMENT \'Time run judging started\''); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE judging_run DROP start_time'); + } + + public function isTransactional(): bool + { + return false; + } +} diff --git a/webapp/src/Controller/API/JudgehostController.php b/webapp/src/Controller/API/JudgehostController.php index 5f9523ff4e..1045447fa1 100644 --- a/webapp/src/Controller/API/JudgehostController.php +++ b/webapp/src/Controller/API/JudgehostController.php @@ -644,6 +644,8 @@ public function addJudgingRunAction( } $runResult = $request->request->get('runresult'); + $startTime = $request->request->get('start_time'); + $endTime = $request->request->get('end_time'); $runTime = $request->request->get('runtime'); $outputRun = $request->request->get('output_run'); $outputDiff = $request->request->get('output_diff'); @@ -659,7 +661,7 @@ public function addJudgingRunAction( throw new BadRequestHttpException("Who are you and why are you sending us any data?"); } - $hasFinalResult = $this->addSingleJudgingRun($judgeTaskId, $hostname, $runResult, $runTime, + $hasFinalResult = $this->addSingleJudgingRun($judgeTaskId, $hostname, $runResult, $runTime, $startTime, $endTime, $outputSystem, $outputError, $outputDiff, $outputRun, $teamMessage, $metadata, $testcasedir, $compareMeta); $judgehost = $this->em->getRepository(Judgehost::class)->findOneBy(['hostname' => $hostname]); $judgehost->setPolltime(Utils::now()); @@ -924,6 +926,8 @@ private function addSingleJudgingRun( string $hostname, string $runResult, string $runTime, + string $startTime, + string $endTime, string $outputSystem, string $outputError, string $outputDiff, @@ -945,6 +949,8 @@ private function addSingleJudgingRun( $this->em->wrapInTransaction(function () use ( $judgeTaskId, $runTime, + $startTime, + $endTime, $runResult, $outputSystem, $outputError, @@ -966,7 +972,8 @@ private function addSingleJudgingRun( $judgingRun ->setRunresult($runResult) ->setRuntime((float)$runTime) - ->setEndtime(Utils::now()) + ->setStarttime($startTime) + ->setEndtime($endTime) ->setTestcasedir($testcasedir); $judgingRunOutput ->setOutputRun(base64_decode($outputRun)) diff --git a/webapp/src/Entity/JudgingRun.php b/webapp/src/Entity/JudgingRun.php index 88fddf5436..dc1966a575 100644 --- a/webapp/src/Entity/JudgingRun.php +++ b/webapp/src/Entity/JudgingRun.php @@ -60,6 +60,16 @@ class JudgingRun extends BaseApiEntity #[Serializer\Exclude] private string|float|null $endtime = null; + #[ORM\Column( + type: 'decimal', + precision: 32, + scale: 9, + nullable: true, + options: ['comment' => 'Time run judging started', 'unsigned' => true] + )] + #[Serializer\Exclude] + private string|float|null $startTime = null; + #[ORM\ManyToOne(inversedBy: 'runs')] #[ORM\JoinColumn(name: 'judgingid', referencedColumnName: 'judgingid', onDelete: 'CASCADE')] #[Serializer\Exclude] @@ -157,6 +167,17 @@ public function setEndtime(string|float $endtime): JudgingRun return $this; } + public function setStarttime(string|float $startTime): JudgingRun + { + $this->startTime = $startTime; + return $this; + } + + public function getStarttime(): string|float|null + { + return $this->startTime; + } + public function getEndtime(): string|float|null { return $this->endtime;