mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
perf(docker): look up foreign preview owners once per container status check
GetContainersStatus now resolves all unknown preview owners with one query, like the Sentinel push. The lookup helper also no longer fails on an application without a uuid.
This commit is contained in:
@@ -106,6 +106,14 @@ class GetContainersStatus
|
||||
$foundDatabases = [];
|
||||
$foundServices = [];
|
||||
|
||||
// Owners of preview containers outside this server's applications, in one query.
|
||||
$foreignApplicationIdsByUuid = containerApplicationIdsByUuid(
|
||||
$this->applications,
|
||||
$this->containers
|
||||
->map(fn ($container) => format_docker_labels_to_json(data_get($container, $this->server->isSwarm() ? 'Spec.Labels' : 'Config.Labels') ?? []))
|
||||
->filter(fn (Collection $labels) => (bool) $labels->get('coolify.pullRequestId') && isContainerOfType($labels, 'application'))
|
||||
);
|
||||
|
||||
foreach ($this->containers as $container) {
|
||||
if ($this->server->isSwarm()) {
|
||||
$labels = data_get($container, 'Spec.Labels');
|
||||
@@ -136,7 +144,7 @@ class GetContainersStatus
|
||||
if ($isApplicationContainer) {
|
||||
$pullRequestId = data_get($labels, 'coolify.pullRequestId');
|
||||
if ($pullRequestId) {
|
||||
$applicationId = resolveContainerApplicationId($this->applications, $flatLabels);
|
||||
$applicationId = resolveContainerApplicationId($this->applications, $flatLabels, $foreignApplicationIdsByUuid);
|
||||
$preview = $applicationId
|
||||
? ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first()
|
||||
: null;
|
||||
|
||||
@@ -154,14 +154,16 @@ function resolveContainerApplicationId(Collection $applications, Collection|arra
|
||||
*/
|
||||
function containerApplicationIdsByUuid(Collection $applications, iterable $containerLabels): array
|
||||
{
|
||||
$knownUuids = $applications->pluck('uuid')->flip();
|
||||
$uuids = [];
|
||||
foreach ($containerLabels as $labels) {
|
||||
$uuid = containerOwnerUuid($labels, 'application');
|
||||
if ($uuid && ! $knownUuids->has($uuid)) {
|
||||
if ($uuid) {
|
||||
$uuids[$uuid] = true;
|
||||
}
|
||||
}
|
||||
foreach ($applications->pluck('uuid')->filter() as $knownUuid) {
|
||||
unset($uuids[$knownUuid]);
|
||||
}
|
||||
if ($uuids === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -311,6 +311,57 @@ describe('status updates after a server transfer', function () {
|
||||
|
||||
expect($this->application->fresh()->status)->toStartWith('running');
|
||||
});
|
||||
|
||||
test('container status check looks up foreign preview owners with one query for all containers', function () {
|
||||
$deleted = Application::factory()->create([
|
||||
'environment_id' => $this->environment->id,
|
||||
'destination_id' => $this->destination->id,
|
||||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
$preview = ApplicationPreview::forceCreate([
|
||||
'application_id' => $deleted->id,
|
||||
'pull_request_id' => 3,
|
||||
'pull_request_html_url' => 'https://example.com/pr/3',
|
||||
'status' => 'exited',
|
||||
]);
|
||||
$deleted->delete();
|
||||
|
||||
$containers = collect(range(1, 5))->map(fn (int $i) => [
|
||||
'Name' => "/foreign-app-{$i}-pr-{$i}",
|
||||
'State' => ['Status' => 'running', 'Health' => ['Status' => 'healthy']],
|
||||
'RestartCount' => 0,
|
||||
'Config' => ['Labels' => [
|
||||
'coolify.managed' => 'true',
|
||||
'coolify.applicationUuid' => "foreign-app-{$i}",
|
||||
'coolify.pullRequestId' => (string) $i,
|
||||
'com.docker.compose.service' => "foreign-app-{$i}-pr-{$i}",
|
||||
]],
|
||||
])->push([
|
||||
'Name' => '/'.$deleted->uuid.'-pr-3',
|
||||
'State' => ['Status' => 'running', 'Health' => ['Status' => 'healthy']],
|
||||
'RestartCount' => 0,
|
||||
'Config' => ['Labels' => [
|
||||
'coolify.managed' => 'true',
|
||||
'coolify.applicationUuid' => $deleted->uuid,
|
||||
'coolify.pullRequestId' => '3',
|
||||
'com.docker.compose.service' => $deleted->uuid.'-pr-3',
|
||||
]],
|
||||
]);
|
||||
|
||||
$this->server->settings()->update(['is_reachable' => true, 'is_usable' => true]);
|
||||
$server = $this->server->fresh();
|
||||
|
||||
DB::enableQueryLog();
|
||||
GetContainersStatus::run($server, $containers, collect());
|
||||
$ownerLookups = collect(DB::getQueryLog())
|
||||
->filter(fn (array $query) => str_contains($query['query'], 'from "applications"') && preg_match('/"uuid" (=|in) /', $query['query']) === 1)
|
||||
->count();
|
||||
DB::disableQueryLog();
|
||||
|
||||
expect($ownerLookups)->toBe(1)
|
||||
// The preview of a trashed owner still resolves.
|
||||
->and($preview->fresh()->status)->toBe('running:healthy');
|
||||
});
|
||||
});
|
||||
|
||||
describe('orphaned preview cleanup', function () {
|
||||
|
||||
Reference in New Issue
Block a user