diff --git a/NEWS.md b/NEWS.md index d0266c299a..d8c6521009 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,7 +18,7 @@ - Re-added “Next” button on smartphones. ([#1406](https://github.com/fossar/selfoss/issues/1406) - Fix compressed SVG (svgz) support. ([#1418](https://github.com/fossar/selfoss/pulls/1418) - Fix article links containing HTML-special characters. ([#1407](https://github.com/fossar/selfoss/issues/1407)) -- Reduce the chance of “Update all sources” button timing out. ([#1428](https://github.com/fossar/selfoss/pulls/1428)) +- Reduce the chance of “Update all sources” button timing out. ([#1428](https://github.com/fossar/selfoss/pulls/1428), [#1430](https://github.com/fossar/selfoss/pulls/1430)) - Fix a log-in loop in client. ([#1429](https://github.com/fossar/selfoss/pulls/1429)) - Fix errors in Firefox’s private browsing mode. diff --git a/assets/js/requests/sources.js b/assets/js/requests/sources.js index e41f60bd43..ac898025d3 100644 --- a/assets/js/requests/sources.js +++ b/assets/js/requests/sources.js @@ -33,7 +33,7 @@ export function refreshAll() { 'Accept': 'text/event-stream', }, timeout: 0, - }).promise; + }).promise.then(response => response.text()); } /** diff --git a/src/controllers/Sources/Update.php b/src/controllers/Sources/Update.php index 890ac0f808..c3dfd1eae4 100644 --- a/src/controllers/Sources/Update.php +++ b/src/controllers/Sources/Update.php @@ -45,23 +45,44 @@ public function updateAll(): void { $reportProgress = $accept === 'text/event-stream'; if ($reportProgress) { + // Individual events are short so we need to prevent various layers in the stack from buffering the response body. + // Otherwise a consuming layer may time out before any output gets to it. + + // Ensure PHP compression is disabled since it would enable output buffering. + // https://www.php.net/manual/en/zlib.configuration.php#ini.zlib.output-compression + ini_set('zlib.output_compression', '0'); + + // End implicit buffering caused by `output_buffering` option. + while (ob_get_level() > 0) { + ob_end_clean(); + } + + // Ask nginx to not buffer FastCGI response. + // http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_buffering + header('X-Accel-Buffering: no'); + // Server-sent events inspired response format. header('Content-Type: text/event-stream'); $updateVisitor = new class() implements UpdateVisitor { private int $finishedCount = 0; + private function sendEvent(string $type, string $data = '{}'): void { + echo "event: {$type}\ndata: {$data}\n\n"; + flush(); + } + public function started(int $count): void { - echo "event: started\ndata: {\"count\": {$count}}\n\n"; + $this->sendEvent('started', "{\"count\": {$count}}"); } public function sourceUpdated(): void { ++$this->finishedCount; - echo "event: sourceUpdated\ndata: {\"finishedCount\": {$this->finishedCount}}\n\n"; + $this->sendEvent('sourceUpdated', "{\"finishedCount\": {$this->finishedCount}}"); } public function finished(): void { - echo "event: finished\ndata: {}\n\n"; + $this->sendEvent('finished'); } }; } else {