From afe4a00318656e2330b65104c339ed484935e24c Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Wed, 29 Apr 2026 09:47:19 +0100 Subject: [PATCH 1/2] fix(activity:log): strip stray query params from log stream URL The activity log link, resolved via Platformsh\Client\Model\Activity::getLink('log'), inherits the query string of the base URL the activity was loaded with. When the activity collection is fetched with a 'count' parameter, that parameter is carried into the absolute log URL by ApiResourceBase::makeAbsoluteUrl(), which only swaps the path. The log endpoint rejects 'count' with HTTP 400, producing repeated fopen warnings in verbose mode and breaking the streaming retry loop. Strip the query string before opening the stream. The non-streaming readLog() path (Activity::fetchLog -> Guzzle 'query' option) already replaces the query string and is unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) --- legacy/src/Service/ActivityMonitor.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/legacy/src/Service/ActivityMonitor.php b/legacy/src/Service/ActivityMonitor.php index f983fb05..7d6ef9fc 100644 --- a/legacy/src/Service/ActivityMonitor.php +++ b/legacy/src/Service/ActivityMonitor.php @@ -685,6 +685,13 @@ private function getLogStream(Activity $activity, ProgressBar $bar) { $url = $activity->getLink('log'); + // Strip any query string from the URL. The log link can inherit query + // parameters (such as "count") from the base activities collection + // URL, and those are rejected by the log endpoint with HTTP 400. + if (($queryPos = \strpos($url, '?')) !== false) { + $url = \substr($url, 0, $queryPos); + } + // Try fetching the stream with a 10 second timeout per call, and a .5 // second interval between calls, for up to 2 minutes. $readTimeout = 10; From d6c4611fc635cd0db0651e67cf4a5b83468cc776 Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Wed, 29 Apr 2026 09:47:35 +0100 Subject: [PATCH 2/2] fix(activity:log): wait the intended 0.5s between log stream retries Operator precedence made (int) $interval * 1000000 evaluate as ((int) 0.5) * 1000000, so the retry loop in getLogStream() called usleep(0) and spun as fast as PHP could re-issue fopen on a failing log endpoint. Wrap the multiplication in parentheses so the intended 500000 microsecond delay is applied. Co-Authored-By: Claude Opus 4.7 (1M context) --- legacy/src/Service/ActivityMonitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy/src/Service/ActivityMonitor.php b/legacy/src/Service/ActivityMonitor.php index 7d6ef9fc..bc4afef2 100644 --- a/legacy/src/Service/ActivityMonitor.php +++ b/legacy/src/Service/ActivityMonitor.php @@ -712,7 +712,7 @@ private function getLogStream(Activity $activity, ProgressBar $bar) throw new \RuntimeException('Failed to open activity log stream: ' . $url); } $bar->advance(); - \usleep((int) $interval * 1000000); + \usleep((int) ($interval * 1000000)); $bar->advance(); $stream = \fopen($url, 'r', false, $this->api->getStreamContext($readTimeout)); }