fix: optimize queries and caching for projects and environments

This commit is contained in:
Andras Bacsai
2026-01-16 11:51:26 +01:00
parent 51301fd12e
commit 95091e918f
9 changed files with 203 additions and 35 deletions
+5 -1
View File
@@ -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)
+40
View File
@@ -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 = [
+22
View File
@@ -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');
+22
View File
@@ -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');