fix: Prevent N+1 query in LocalPersistentVolume.isDockerComposeResource()

Use relationLoaded() check before accessing the application relationship
to avoid triggering individual queries for each volume when rendering
storage lists. Update Storage.php to eager load the relationship.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai 2025-12-11 21:23:46 +01:00
parent f152ec00ad
commit 475cfd78cd
2 changed files with 54 additions and 1 deletions

View file

@ -67,7 +67,7 @@ public function refreshStoragesFromEvent()
public function refreshStorages()
{
$this->fileStorage = $this->resource->fileStorages()->get();
$this->resource->refresh();
$this->resource->load('persistentStorages.resource');
}
public function getFilesProperty()

View file

@ -10,6 +10,11 @@ class LocalPersistentVolume extends Model
{
protected $guarded = [];
public function resource()
{
return $this->morphTo('resource');
}
public function application()
{
return $this->morphTo('resource');
@ -50,6 +55,54 @@ protected function hostPath(): Attribute
);
}
// Check if this volume belongs to a service resource
public function isServiceResource(): bool
{
return in_array($this->resource_type, [
'App\Models\ServiceApplication',
'App\Models\ServiceDatabase',
]);
}
// Check if this volume belongs to a dockercompose application
public function isDockerComposeResource(): bool
{
if ($this->resource_type !== 'App\Models\Application') {
return false;
}
// Only access relationship if already eager loaded to avoid N+1
if (! $this->relationLoaded('resource')) {
return false;
}
$application = $this->resource;
if (! $application) {
return false;
}
return data_get($application, 'build_pack') === 'dockercompose';
}
// Determine if this volume should be read-only in the UI
// Service volumes and dockercompose application volumes are read-only
// (users should edit compose file directly)
public function shouldBeReadOnlyInUI(): bool
{
// All service volumes should be read-only in UI
if ($this->isServiceResource()) {
return true;
}
// All dockercompose application volumes should be read-only in UI
if ($this->isDockerComposeResource()) {
return true;
}
// Check for explicit :ro flag in compose (existing logic)
return $this->isReadOnlyVolume();
}
// Check if this volume is read-only by parsing the docker-compose content
public function isReadOnlyVolume(): bool
{