mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
fix: optimize queries and caching for projects and environments
This commit is contained in:
@@ -33,6 +33,10 @@ class Index extends Component
|
||||
|
||||
public Collection $services;
|
||||
|
||||
public Collection $allProjects;
|
||||
|
||||
public Collection $allEnvironments;
|
||||
|
||||
public array $parameters;
|
||||
|
||||
public function mount()
|
||||
@@ -50,6 +54,33 @@ class Index extends Component
|
||||
->firstOrFail();
|
||||
|
||||
$this->project = $project;
|
||||
|
||||
// Load projects and environments for breadcrumb navigation (avoids inline queries in view)
|
||||
$this->allProjects = Project::ownedByCurrentTeamCached();
|
||||
$this->allEnvironments = $project->environments()
|
||||
->with([
|
||||
'applications.additional_servers',
|
||||
'applications.destination.server',
|
||||
'services',
|
||||
'services.destination.server',
|
||||
'postgresqls',
|
||||
'postgresqls.destination.server',
|
||||
'redis',
|
||||
'redis.destination.server',
|
||||
'mongodbs',
|
||||
'mongodbs.destination.server',
|
||||
'mysqls',
|
||||
'mysqls.destination.server',
|
||||
'mariadbs',
|
||||
'mariadbs.destination.server',
|
||||
'keydbs',
|
||||
'keydbs.destination.server',
|
||||
'dragonflies',
|
||||
'dragonflies.destination.server',
|
||||
'clickhouses',
|
||||
'clickhouses.destination.server',
|
||||
])->get();
|
||||
|
||||
$this->environment = $environment->loadCount([
|
||||
'applications',
|
||||
'redis',
|
||||
@@ -71,11 +102,13 @@ class Index extends Component
|
||||
'destination.server.settings',
|
||||
'settings',
|
||||
])->get()->sortBy('name');
|
||||
$this->applications = $this->applications->map(function ($application) {
|
||||
$projectUuid = $this->project->uuid;
|
||||
$environmentUuid = $this->environment->uuid;
|
||||
$this->applications = $this->applications->map(function ($application) use ($projectUuid, $environmentUuid) {
|
||||
$application->hrefLink = route('project.application.configuration', [
|
||||
'project_uuid' => data_get($application, 'environment.project.uuid'),
|
||||
'environment_uuid' => data_get($application, 'environment.uuid'),
|
||||
'application_uuid' => data_get($application, 'uuid'),
|
||||
'project_uuid' => $projectUuid,
|
||||
'environment_uuid' => $environmentUuid,
|
||||
'application_uuid' => $application->uuid,
|
||||
]);
|
||||
|
||||
return $application;
|
||||
@@ -98,11 +131,11 @@ class Index extends Component
|
||||
'tags',
|
||||
'destination.server.settings',
|
||||
])->get()->sortBy('name');
|
||||
$this->{$property} = $this->{$property}->map(function ($db) {
|
||||
$this->{$property} = $this->{$property}->map(function ($db) use ($projectUuid, $environmentUuid) {
|
||||
$db->hrefLink = route('project.database.configuration', [
|
||||
'project_uuid' => $this->project->uuid,
|
||||
'project_uuid' => $projectUuid,
|
||||
'database_uuid' => $db->uuid,
|
||||
'environment_uuid' => data_get($this->environment, 'uuid'),
|
||||
'environment_uuid' => $environmentUuid,
|
||||
]);
|
||||
|
||||
return $db;
|
||||
@@ -114,11 +147,11 @@ class Index extends Component
|
||||
'tags',
|
||||
'destination.server.settings',
|
||||
])->get()->sortBy('name');
|
||||
$this->services = $this->services->map(function ($service) {
|
||||
$this->services = $this->services->map(function ($service) use ($projectUuid, $environmentUuid) {
|
||||
$service->hrefLink = route('project.service.configuration', [
|
||||
'project_uuid' => data_get($service, 'environment.project.uuid'),
|
||||
'environment_uuid' => data_get($service, 'environment.uuid'),
|
||||
'service_uuid' => data_get($service, 'uuid'),
|
||||
'project_uuid' => $projectUuid,
|
||||
'environment_uuid' => $environmentUuid,
|
||||
'service_uuid' => $service->uuid,
|
||||
]);
|
||||
|
||||
return $service;
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Once;
|
||||
use Spatie\Url\Url;
|
||||
|
||||
class InstanceSettings extends Model
|
||||
@@ -35,6 +36,9 @@ class InstanceSettings extends Model
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::updated(function ($settings) {
|
||||
// Clear once() cache so subsequent calls get fresh data
|
||||
Once::flush();
|
||||
|
||||
// Clear trusted hosts cache when FQDN changes
|
||||
if ($settings->wasChanged('fqdn')) {
|
||||
\Cache::forget('instance_settings_fqdn_host');
|
||||
@@ -82,7 +86,7 @@ class InstanceSettings extends Model
|
||||
|
||||
public static function get()
|
||||
{
|
||||
return InstanceSettings::findOrFail(0);
|
||||
return once(fn () => InstanceSettings::findOrFail(0));
|
||||
}
|
||||
|
||||
// public function getRecipients($notification)
|
||||
|
||||
@@ -108,6 +108,12 @@ class Server extends BaseModel
|
||||
|
||||
public static $batch_counter = 0;
|
||||
|
||||
/**
|
||||
* Identity map cache for request-scoped Server lookups.
|
||||
* Prevents N+1 queries when the same Server is accessed multiple times.
|
||||
*/
|
||||
private static ?array $identityMapCache = null;
|
||||
|
||||
protected $appends = ['is_coolify_host'];
|
||||
|
||||
protected static function booted()
|
||||
@@ -186,6 +192,40 @@ class Server extends BaseModel
|
||||
$server->settings()->delete();
|
||||
$server->sslCertificates()->delete();
|
||||
});
|
||||
|
||||
static::updated(function () {
|
||||
static::flushIdentityMap();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a Server by ID using the identity map cache.
|
||||
* This prevents N+1 queries when the same Server is accessed multiple times.
|
||||
*/
|
||||
public static function findCached($id): ?static
|
||||
{
|
||||
if ($id === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (static::$identityMapCache === null) {
|
||||
static::$identityMapCache = [];
|
||||
}
|
||||
|
||||
if (! isset(static::$identityMapCache[$id])) {
|
||||
static::$identityMapCache[$id] = static::query()->find($id);
|
||||
}
|
||||
|
||||
return static::$identityMapCache[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the identity map cache.
|
||||
* Called automatically on update, and should be called in tests.
|
||||
*/
|
||||
public static function flushIdentityMap(): void
|
||||
{
|
||||
static::$identityMapCache = null;
|
||||
}
|
||||
|
||||
protected $casts = [
|
||||
|
||||
@@ -73,6 +73,28 @@ class StandaloneDocker extends BaseModel
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server attribute using identity map caching.
|
||||
* This intercepts lazy-loading to use cached Server lookups.
|
||||
*/
|
||||
public function getServerAttribute(): ?Server
|
||||
{
|
||||
// Use eager loaded data if available
|
||||
if ($this->relationLoaded('server')) {
|
||||
return $this->getRelation('server');
|
||||
}
|
||||
|
||||
// Use identity map for lazy loading
|
||||
$server = Server::findCached($this->server_id);
|
||||
|
||||
// Cache in relation for future access on this instance
|
||||
if ($server) {
|
||||
$this->setRelation('server', $server);
|
||||
}
|
||||
|
||||
return $server;
|
||||
}
|
||||
|
||||
public function services()
|
||||
{
|
||||
return $this->morphMany(Service::class, 'destination');
|
||||
|
||||
@@ -56,6 +56,28 @@ class SwarmDocker extends BaseModel
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server attribute using identity map caching.
|
||||
* This intercepts lazy-loading to use cached Server lookups.
|
||||
*/
|
||||
public function getServerAttribute(): ?Server
|
||||
{
|
||||
// Use eager loaded data if available
|
||||
if ($this->relationLoaded('server')) {
|
||||
return $this->getRelation('server');
|
||||
}
|
||||
|
||||
// Use identity map for lazy loading
|
||||
$server = Server::findCached($this->server_id);
|
||||
|
||||
// Cache in relation for future access on this instance
|
||||
if ($server) {
|
||||
$this->setRelation('server', $server);
|
||||
}
|
||||
|
||||
return $server;
|
||||
}
|
||||
|
||||
public function services()
|
||||
{
|
||||
return $this->morphMany(Service::class, 'destination');
|
||||
|
||||
Reference in New Issue
Block a user