mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(cdn): fetch versions.json once per hour, spread evenly across instances
- Retry CDN requests only for transient errors and honor Retry-After (Cloudflare error 1200 sends 60 s), with jitter. - Read helper and Sentinel versions from the local versions.json, which the hourly update check refreshes, instead of fetching per job/server. - Replace the random 0-600 s delay with a stable per-instance offset inside the cron interval (max 1 h). - Manual update checks and upgrades make one CDN attempt only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
44c6322259
commit
dbc3fb91bf
@@ -703,14 +703,8 @@ function get_route_parameters(): array
|
||||
|
||||
function get_latest_sentinel_version(): string
|
||||
{
|
||||
try {
|
||||
$response = Http::get(config('constants.coolify.versions_url'));
|
||||
$versions = $response->json();
|
||||
|
||||
return data_get($versions, 'coolify.sentinel.version');
|
||||
} catch (Throwable) {
|
||||
return '0.0.0';
|
||||
}
|
||||
// Read the local versions.json, which CheckForUpdatesJob refreshes every hour. Do not ask the CDN for each server.
|
||||
return data_get(get_versions_data(), 'coolify.sentinel.version') ?? '0.0.0';
|
||||
}
|
||||
function get_latest_version_of_coolify(): string
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Http\Client\ConnectionException;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@@ -54,6 +57,37 @@ function invalidate_versions_cache(): void
|
||||
Cache::forget('coolify:versions:all');
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP client for the Coolify CDN. It retries only transient failures (connection errors, 429, 5xx)
|
||||
* and does not throw for a failed response.
|
||||
*/
|
||||
function cdn_http(int $tries = 3): PendingRequest
|
||||
{
|
||||
return Http::timeout(10)
|
||||
->connectTimeout(10)
|
||||
->retry(
|
||||
$tries,
|
||||
fn (int $attempt, Throwable $exception) => cdn_retry_delay_ms($attempt, $exception),
|
||||
fn (Throwable $exception) => $exception instanceof ConnectionException
|
||||
|| ($exception instanceof RequestException
|
||||
&& ($exception->response->status() === 429 || $exception->response->serverError())),
|
||||
throw: false,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait as long as the Retry-After header says (Cloudflare sends 60 seconds with error 1200),
|
||||
* or 2^attempt seconds without it. A random part of up to the same length is added, so instances
|
||||
* that failed in the same burst do not retry in the same second.
|
||||
*/
|
||||
function cdn_retry_delay_ms(int $attempt, Throwable $exception): int
|
||||
{
|
||||
$retryAfter = $exception instanceof RequestException ? (int) $exception->response->header('Retry-After') : 0;
|
||||
$seconds = $retryAfter > 0 ? min($retryAfter, 60) : 2 ** $attempt;
|
||||
|
||||
return ($seconds + random_int(0, $seconds)) * 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch versions.json from the CDN and write it to the local file of this node.
|
||||
* The Coolify version never goes below the cached or the running version.
|
||||
@@ -61,9 +95,9 @@ function invalidate_versions_cache(): void
|
||||
*
|
||||
* @return array|null The written versions data, or null if the CDN fetch failed
|
||||
*/
|
||||
function refresh_versions_file(): ?array
|
||||
function refresh_versions_file(int $tries = 3): ?array
|
||||
{
|
||||
$response = Http::timeout(10)->retry(3, 1000, throw: false)->get(config('constants.coolify.versions_url'));
|
||||
$response = cdn_http($tries)->get(config('constants.coolify.versions_url'));
|
||||
$versions = $response->json();
|
||||
if ($response->failed() || ! is_array($versions)) {
|
||||
Log::warning('Could not fetch versions.json from the CDN, using the local file', ['status' => $response->status()]);
|
||||
@@ -106,6 +140,19 @@ function refresh_versions_file(): ?array
|
||||
|
||||
File::put(base_path('versions.json'), json_encode($versions, JSON_PRETTY_PRINT));
|
||||
invalidate_versions_cache();
|
||||
update_helper_version($versions);
|
||||
|
||||
return $versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the helper image version of the versions data when it is newer than the stored one.
|
||||
*/
|
||||
function update_helper_version(?array $versions): void
|
||||
{
|
||||
$latestVersion = data_get($versions, 'coolify.helper.version');
|
||||
$settings = instanceSettings();
|
||||
if ($latestVersion && version_compare($latestVersion, (string) $settings->helper_version, '>')) {
|
||||
$settings->update(['helper_version' => $latestVersion]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user