fix(servers): skip patch check results in bulk settings loads

ServerManagerJob and the Docker cleanup step of ScheduledJobManager
load the settings of every server with SELECT *. That reads the
patch_check_result JSON, which holds the full update list of each
server. With 12,709 rows, the scan took about 4 ms, but the full fetch
took 390-536 ms and 294 MB of PHP memory. Without the column it took
74 ms and 111 MB.

Add ServerSetting::withoutPatchCheckResult() and use it in both loops.
Queued jobs reload the full settings through SerializesModels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-28 23:58:51 +01:00
co-authored by Claude Opus 5.5
parent c34f5f8e3b
commit 3d956c110c
5 changed files with 143 additions and 3 deletions
+16
View File
@@ -5,10 +5,12 @@ namespace App\Models;
use App\Enums\ServerRole;
use App\Enums\TrafficIpMode;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use OpenApi\Attributes as OA;
#[OA\Schema(
@@ -231,6 +233,9 @@ class ServerSetting extends Model
'geoip_maxmind_license_key',
];
/** @var list<string>|null */
private static ?array $columnsWithoutPatchCheckResult = null;
protected static function booted()
{
static::creating(function ($setting) {
@@ -465,6 +470,17 @@ class ServerSetting extends Model
);
}
/**
* Selects every column except patch_check_result, which holds the full update list of the last patch
* check (often tens of kilobytes). Use it for instance-wide server loops that do not read the result.
*/
public function scopeWithoutPatchCheckResult(Builder $query): Builder
{
self::$columnsWithoutPatchCheckResult ??= array_values(array_diff(Schema::getColumnListing($this->getTable()), ['patch_check_result']));
return $query->select(self::$columnsWithoutPatchCheckResult);
}
/**
* Summary of the saved patch check, or null when the server was never checked.
* Results saved before security and reboot detection count as 0 and false.