Current state with latest updates

This commit is contained in:
2026-08-23 13:28:34 +02:00
parent 5af95f6533
commit f52879edbb
74 changed files with 5174 additions and 960 deletions
@@ -7,8 +7,10 @@ namespace App\Services\Images;
use App\Models\Artwork;
use App\Services\Cdn\ArtworkCdnPurgeService;
use App\Services\ArtworkOriginalFileLocator;
use App\Services\HomepageService;
use App\Services\Uploads\UploadStorageService;
use App\Support\ArtworkFeaturedImagePath;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Drivers\Gd\Driver as GdDriver;
@@ -28,6 +30,7 @@ final class FeaturedArtworkThumbnailGenerator
private readonly ArtworkOriginalFileLocator $locator,
private readonly UploadStorageService $storage,
private readonly ArtworkCdnPurgeService $cdnPurge,
private readonly HomepageService $homepage,
) {
try {
$this->manager = extension_loaded('gd')
@@ -59,6 +62,8 @@ final class FeaturedArtworkThumbnailGenerator
$missing[] = $variant;
}
$this->persistVariantState($artwork, $existing);
return [
'existing' => $existing,
'missing' => $missing,
@@ -66,6 +71,52 @@ final class FeaturedArtworkThumbnailGenerator
];
}
/**
* Record which featured variants are known to exist so the public homepage can read
* this state instead of checking the remote disk during a request.
*
* saveQuietly() intentionally bypasses model observers (ArtworkObserver /
* ArtworkFeatureObserver never fire for this write), so cache invalidation for the
* homepage hero cannot be delegated to them here — it has to happen inline, and only
* when the persisted availability actually changed for an artwork that is currently
* an active feature (otherwise routine --all/--missing-only audits over thousands of
* non-featured artworks would repeatedly invalidate the guest payload cache for no
* reason and cause a stampede).
*
* @param list<string> $existingVariants
*/
private function persistVariantState(Artwork $artwork, array $existingVariants): void
{
$existingVariants = array_values(array_unique($existingVariants));
sort($existingVariants);
$previousVariants = (array) ($artwork->featured_thumbnail_variants_json ?? []);
sort($previousVariants);
$changed = $previousVariants !== $existingVariants;
$artwork->forceFill([
'featured_thumbnail_variants_json' => $existingVariants,
'featured_thumbnails_checked_at' => now(),
])->saveQuietly();
if ($changed && $this->isActivelyFeatured($artwork)) {
$this->homepage->clearFeaturedAndMedalCaches();
}
}
private function isActivelyFeatured(Artwork $artwork): bool
{
return DB::table('artwork_features')
->where('artwork_id', $artwork->id)
->where('is_active', true)
->whereNull('deleted_at')
->where(function ($query): void {
$query->whereNull('expires_at')->orWhere('expires_at', '>', now());
})
->exists();
}
/**
* @return array{existing:list<string>,missing:list<string>,target_variants:list<string>,generated:int,skipped:int,generated_variants:list<string>,generated_paths:list<string>,failed:array<string,string>}
*/
@@ -129,6 +180,10 @@ final class FeaturedArtworkThumbnailGenerator
]);
}
if ($generatedVariants !== []) {
$this->persistVariantState($artwork, array_values(array_unique([...$plan['existing'], ...$generatedVariants])));
}
return $plan + [
'generated' => count($generatedVariants),
'skipped' => max(0, count($targetVariants) - count($generatedVariants) - count($failed)) + count($plan['existing']),