Skip to content

Commit 28d7972

Browse files
committed
Replace async reporting back of results with guzzle.
Previously, we were in an ugly way calling the judgedaemon again. A later step can be to replace all curl calls with guzzle.
1 parent 74a851b commit 28d7972

File tree

3 files changed

+42
-47
lines changed

3 files changed

+42
-47
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ build-scripts:
8686
build: SUBDIRS= lib misc-tools
8787
domserver: SUBDIRS=etc sql misc-tools webapp
8888
install-domserver: SUBDIRS=etc lib sql misc-tools webapp example_problems
89-
judgehost: SUBDIRS=etc judge misc-tools
89+
judgehost: SUBDIRS=etc judge misc-tools webapp
9090
install-judgehost: SUBDIRS=etc lib judge misc-tools
9191
docs: SUBDIRS= doc
9292
install-docs: SUBDIRS= doc

judge/judgedaemon.main.php

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?php declare(strict_types=1);
2+
3+
require_once __DIR__ . '/../vendor/autoload.php';
24
/**
35
* Requests a batch of judge tasks the domserver, executes them and reports
46
* the results back to the domserver.
@@ -13,6 +15,10 @@
1315
require(ETCDIR . '/judgehost-config.php');
1416
require(LIBDIR . '/lib.misc.php');
1517

18+
use GuzzleHttp\Client;
19+
use GuzzleHttp\Handler\CurlMultiHandler;
20+
use GuzzleHttp\HandlerStack;
21+
1622
$endpoints = [];
1723
$domjudge_config = [];
1824

@@ -537,7 +543,7 @@ function fetch_executable_internal(
537543
return [$execrunpath, null, null];
538544
}
539545

540-
$options = getopt("dv:n:hVe:j:t:", ["diskspace-error"]);
546+
$options = getopt("dv:n:hV", ["diskspace-error"]);
541547
// We can't fully trust the output of getopt, it has outstanding bugs:
542548
// https://bugs.php.net/search.php?cmd=display&search_for=getopt&x=0&y=0
543549
if ($options===false) {
@@ -658,39 +664,7 @@ function fetch_executable_internal(
658664

659665
read_credentials();
660666

661-
if (!empty($options['e'])) {
662-
$endpointID = $options['e'];
663-
$endpoint = $endpoints[$endpointID];
664-
$endpoints[$endpointID]['ch'] = setup_curl_handle($endpoint['user'], $endpoint['pass']);
665-
$new_judging_run = (array) dj_json_decode(base64_decode(file_get_contents($options['j'])));
666-
$judgeTaskId = $options['t'];
667-
668-
$success = false;
669-
for ($i = 0; $i < 5; $i++) {
670-
if ($i > 0) {
671-
$sleep_ms = 100 + random_int(200, ($i+1)*1000);
672-
dj_sleep(0.001 * $sleep_ms);
673-
}
674-
$response = request(
675-
sprintf('judgehosts/add-judging-run/%s/%s', $new_judging_run['hostname'],
676-
urlencode((string)$judgeTaskId)),
677-
'POST',
678-
$new_judging_run,
679-
false
680-
);
681-
if ($response !== null) {
682-
logmsg(LOG_DEBUG, "Adding judging run result for jt$judgeTaskId successful.");
683-
$success = true;
684-
break;
685-
}
686-
logmsg(LOG_WARNING, "Failed to report jt$judgeTaskId in attempt #" . ($i + 1) . ".");
687-
}
688-
if (!$success) {
689-
error("Final attempt of uploading jt$judgeTaskId was unsuccessful, giving up.");
690-
}
691-
unlink($options['j']);
692-
exit(0);
693-
}
667+
694668

695669
// Set umask to allow group and other access, as this is needed for the
696670
// unprivileged user.
@@ -729,7 +703,14 @@ function fetch_executable_internal(
729703
$endpointIDs = array_keys($endpoints);
730704
$currentEndpoint = 0;
731705
$lastWorkdir = null;
706+
707+
// Set up Guzzle client used for async progress reporting.
708+
$guzzleHandler = new CurlMultiHandler();
709+
$handlerStack = HandlerStack::create($guzzleHandler);
710+
$guzzleClient = new Client(['handler' => $handlerStack, 'timeout' => 30]);
711+
732712
while (true) {
713+
$guzzleHandler->tick(); // process async requests in case there are any
733714
// If all endpoints are waiting, sleep for a bit.
734715
$dosleep = true;
735716
foreach ($endpoints as $id => $endpoint) {
@@ -1026,6 +1007,7 @@ function fetch_executable_internal(
10261007
}
10271008
break;
10281009
}
1010+
$guzzleHandler->tick(); // process async requests in case there are any
10291011
}
10301012

10311013
file_put_contents($success_file, $expected_uuid_pid);
@@ -1349,7 +1331,7 @@ function compile(
13491331

13501332
function judge(array $judgeTask): bool
13511333
{
1352-
global $EXITCODES, $myhost, $options, $workdirpath, $exitsignalled, $gracefulexitsignalled, $endpointID;
1334+
global $EXITCODES, $myhost, $options, $workdirpath, $exitsignalled, $gracefulexitsignalled, $endpointID, $guzzleClient, $endpoints;
13531335
$startTime = microtime(true);
13541336

13551337
$compile_config = dj_json_decode($judgeTask['compile_config']);
@@ -1593,17 +1575,26 @@ function judge(array $judgeTask): bool
15931575

15941576
$ret = true;
15951577
if ($result === 'correct') {
1596-
// Post result back asynchronously. PHP is lacking multi-threading, so
1597-
// we just call ourselves again.
1598-
$tmpfile = tempnam(TMPDIR, 'judging_run_');
1599-
file_put_contents($tmpfile, base64_encode(dj_json_encode($new_judging_run)));
1600-
$judgedaemon = BINDIR . '/judgedaemon';
1601-
$cmd = $judgedaemon
1602-
. ' -e ' . $endpointID
1603-
. ' -t ' . $judgeTask['judgetaskid']
1604-
. ' -j ' . $tmpfile
1605-
. ' >> /dev/null & ';
1606-
shell_exec($cmd);
1578+
// Post result back asynchronously.
1579+
$url = sprintf('%s/judgehosts/add-judging-run/%s/%s', $endpoints[$endpointID]['url'], urlencode($myhost), urlencode((string)$judgeTask['judgetaskid']));
1580+
$auth = [$endpoints[$endpointID]['user'], $endpoints[$endpointID]['pass']];
1581+
1582+
$multipart_data = [];
1583+
foreach ($new_judging_run as $key => $value) {
1584+
$multipart_data[] = [
1585+
'name' => $key,
1586+
'contents' => $value
1587+
];
1588+
}
1589+
1590+
$promise = $guzzleClient->postAsync($url, [
1591+
'auth' => $auth,
1592+
'multipart' => $multipart_data
1593+
]);
1594+
1595+
$promise->then(null, function ($reason) {
1596+
logmsg(LOG_WARNING, "Async submission failed: " . $reason->getMessage());
1597+
});
16071598
} else {
16081599
// This run was incorrect, only continue with the remaining judge tasks
16091600
// if we are told to do so.

webapp/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include $(TOPDIR)/Makefile.global
1010
SUBDIRS = config
1111

1212
domserver: composer-dump-autoload
13+
judgehost: composer-dump-autoload
1314

1415
# Install PHP dependencies
1516
composer-dependencies:
@@ -67,6 +68,9 @@ install-domserver:
6768
ln -sf $(domjudge_docdir) $(DESTDIR)$(domserver_webappdir)/public/doc
6869
$(INSTALL_DATA) -t $(DESTDIR)$(domserver_webappdir) phpunit.xml.dist .env
6970

71+
install-judgehost:
72+
$(call install_tree,$(DESTDIR),vendor)
73+
7074
maintainer-conf: .env.local
7175

7276
maintainer-install: composer-dump-autoload-dev

0 commit comments

Comments
 (0)