mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-28 06:20:14 +00:00
As heartbeat send a dot regularly
Rather than repeating the message, send a "magic" dot, which gets appended to the previous line. Previously the heartbeats weren't sent regulary because reading the data into a buffer caused a lag. Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
This commit is contained in:
@@ -4,6 +4,10 @@ const observer = new MutationObserver((records) => {
|
||||
// function being present.
|
||||
if (node && typeof(node.scrollIntoView) === 'function') {
|
||||
node.scrollIntoView();
|
||||
if (node.classList.contains('progress-indicator')) {
|
||||
node.previousSibling.append('.');
|
||||
node.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(document, {childList: true, subtree: true});
|
||||
|
||||
@@ -435,7 +435,14 @@ readonly class DockerController {
|
||||
// if it'll actually pull an image), but which should not need to know anything about the
|
||||
// wanted markup or formatting.
|
||||
$addToStreamingResponseBody = function (Container $container, string $message) use ($nonbufResp) : void {
|
||||
$nonbufResp->getBody()->write("<div>{$container->displayName}: {$message}</div>");
|
||||
// If the message is a single dot we treat it as a progress indicator and send a specific, empty
|
||||
// HTML element, which gets special treatment by the Javascript code.
|
||||
if ($message === '.') {
|
||||
$content = "<span class='progress-indicator'></span>";
|
||||
} else {
|
||||
$content = "<div>{$container->displayName}: {$message}</div>";
|
||||
}
|
||||
$nonbufResp->getBody()->write($content);
|
||||
};
|
||||
|
||||
return $addToStreamingResponseBody;
|
||||
|
||||
@@ -10,6 +10,7 @@ use AIO\ContainerDefinitionFetcher;
|
||||
use AIO\Data\ConfigurationManager;
|
||||
use AIO\Data\DataConst;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use http\Env\Response;
|
||||
|
||||
@@ -572,41 +573,24 @@ readonly class DockerActionManager {
|
||||
// libcurl and thus the curl option set when creating the client doesn't apply.
|
||||
$pullResponse = $this->guzzleClient->post($url, ['proxy' => 'unix:///var/run/docker.sock', 'stream' => true]);
|
||||
$pullBody = $pullResponse->getBody();
|
||||
$buffer = '';
|
||||
$pullErrors = [];
|
||||
$lastHeartbeat = 0;
|
||||
$lastHeartbeat = time();
|
||||
while (!$pullBody->eof()) {
|
||||
$chunk = $pullBody->read(self::PULL_STREAM_READ_CHUNK_SIZE);
|
||||
if ($chunk === '') {
|
||||
$line = Utils::readLine($pullBody);
|
||||
$event = json_decode($line, true);
|
||||
if (!is_array($event)) {
|
||||
continue;
|
||||
}
|
||||
$buffer .= $chunk;
|
||||
// Guard against malformed responses that contain no newlines.
|
||||
if (strlen($buffer) > self::PULL_STREAM_MAX_BUFFER_SIZE && strpos($buffer, "\n") === false) {
|
||||
error_log('Docker pull response buffer exceeded 1 MB without a newline, discarding buffer for ' . $imageName);
|
||||
$buffer = '';
|
||||
continue;
|
||||
}
|
||||
while (($newlinePos = strpos($buffer, "\n")) !== false) {
|
||||
$line = trim(substr($buffer, 0, $newlinePos));
|
||||
$buffer = substr($buffer, $newlinePos + 1);
|
||||
if ($line === '') {
|
||||
continue;
|
||||
}
|
||||
$event = json_decode($line, true);
|
||||
if (!is_array($event)) {
|
||||
continue;
|
||||
}
|
||||
if (isset($event['error'])) {
|
||||
$pullErrors[] = $event['error'];
|
||||
} elseif ($addToStreamingResponseBody !== null) {
|
||||
// Write a heartbeat at most once every 5 seconds so the reverse
|
||||
// proxy sees continuous data and does not close the connection.
|
||||
$now = time();
|
||||
if ($now - $lastHeartbeat >= self::PULL_HEARTBEAT_INTERVAL_SECONDS) {
|
||||
$addToStreamingResponseBody($container, "Pulling image");
|
||||
$lastHeartbeat = $now;
|
||||
}
|
||||
if (isset($event['error'])) {
|
||||
$pullErrors[] = $event['error'];
|
||||
} elseif ($addToStreamingResponseBody !== null) {
|
||||
// Write a heartbeat at most once every 5 seconds so the reverse
|
||||
// proxy sees continuous data and does not close the connection.
|
||||
$now = time();
|
||||
$interval = time() - $lastHeartbeat;
|
||||
if ($interval >= self::PULL_HEARTBEAT_INTERVAL_SECONDS) {
|
||||
$addToStreamingResponseBody($container, ".");
|
||||
$lastHeartbeat = $now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user