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:
Andras Bacsai
2026-09-30 19:23:35 +02:00
parent 7183e52779
commit 5a2006e99c
3 changed files with 64 additions and 3 deletions
+9 -1
View File
@@ -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;
+4 -2
View File
@@ -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 () {