Wire admin studio SSR and search infrastructure

This commit is contained in:
2026-05-01 11:46:06 +02:00
parent 257b0dbef6
commit 18cea8b0f0
329 changed files with 197465 additions and 2741 deletions

View File

@@ -24,11 +24,6 @@ use App\Console\Commands\RecalculateTrendingCommand;
use App\Console\Commands\RecalculateRankingsCommand;
use App\Console\Commands\MetricsSnapshotHourlyCommand;
use App\Console\Commands\RecalculateHeatCommand;
use App\Jobs\UpdateLeaderboardsJob;
use App\Jobs\RebuildTrendingNovaCardsJob;
use App\Jobs\RecalculateRisingNovaCardsJob;
use App\Jobs\RankComputeArtworkScoresJob;
use App\Jobs\RankBuildListsJob;
use App\Uploads\Commands\CleanupUploadsCommand;
use App\Console\Commands\NormalizeArtworkSlugsCommand;
use App\Console\Commands\PublishScheduledArtworksCommand;
@@ -40,7 +35,10 @@ use App\Console\Commands\PublishSitemapsCommand;
use App\Console\Commands\RollbackSitemapReleaseCommand;
use App\Console\Commands\SyncCollectionLifecycleCommand;
use App\Console\Commands\ValidateSitemapsCommand;
use App\Jobs\Sitemaps\CleanupSitemapReleasesJob;
use App\Console\Commands\AuditArtworkDownloadFilesCommand;
use App\Console\Commands\InspectArtworkOriginalCommand;
use App\Console\Commands\ZipUnsupportedArtworkOriginalsCommand;
use App\Console\Commands\SendTestMail;
class Kernel extends ConsoleKernel
{
@@ -68,6 +66,10 @@ class Kernel extends ConsoleKernel
PublishScheduledNovaCardsCommand::class,
SyncCollectionLifecycleCommand::class,
ValidateSitemapsCommand::class,
AuditArtworkDownloadFilesCommand::class,
InspectArtworkOriginalCommand::class,
ZipUnsupportedArtworkOriginalsCommand::class,
SendTestMail::class,
DispatchCollectionMaintenanceCommand::class,
BackfillArtworkEmbeddingsCommand::class,
BackfillArtworkVectorIndexCommand::class,
@@ -92,6 +94,7 @@ class Kernel extends ConsoleKernel
\App\Console\Commands\AuditOrphanedArtworksCommand::class,
\App\Console\Commands\FlagLegacyUsersForMigrationCommand::class,
\App\Console\Commands\ExportLegacyPasswordsCommand::class,
\App\Console\Commands\HashLegacyPlainPasswordsCommand::class,
\App\Console\Commands\GenerateAiBiographyCommand::class,
\App\Console\Commands\InspectAiBiographyCommand::class,
\App\Console\Commands\ReviewQueueAiBiographyCommand::class,
@@ -103,119 +106,8 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(\Illuminate\Console\Scheduling\Schedule $schedule): void
{
$schedule->command('uploads:cleanup')->dailyAt('03:00');
$schedule->command('skinbase:sitemaps:publish --sync')
->everySixHours()
->name('sitemaps-publish')
->withoutOverlapping()
->runInBackground();
$schedule->command('skinbase:sitemaps:validate')
->dailyAt('04:45')
->name('sitemaps-validate')
->withoutOverlapping()
->runInBackground();
$schedule->job(new CleanupSitemapReleasesJob)
->dailyAt('05:00')
->name('sitemaps-cleanup')
->withoutOverlapping()
->runInBackground();
// Publish artworks whose scheduled publish_at has passed
$schedule->command('artworks:publish-scheduled')
->everyMinute()
->name('publish-scheduled-artworks')
->withoutOverlapping(2) // prevent overlap up to 2 minutes
->runInBackground();
$schedule->command('news:publish-scheduled')
->everyMinute()
->name('publish-scheduled-news')
->withoutOverlapping(2)
->runInBackground();
$schedule->command('nova-cards:publish-scheduled')
->everyMinute()
->name('publish-scheduled-nova-cards')
->withoutOverlapping(2)
->runInBackground();
$schedule->command('collections:sync-lifecycle')
->everyTenMinutes()
->name('sync-collection-lifecycle')
->withoutOverlapping()
->runInBackground();
$schedule->command('collections:dispatch-maintenance')
->hourly()
->name('dispatch-collection-maintenance')
->withoutOverlapping()
->runInBackground();
$schedule->command('analytics:aggregate-similar-artworks')->dailyAt('03:10');
$schedule->command('analytics:aggregate-feed')->dailyAt('03:20');
$schedule->command('analytics:aggregate-tag-interactions')->dailyAt('03:30');
// Recalculate trending scores every 30 minutes (staggered to reduce peak load)
$schedule->command('skinbase:recalculate-trending --period=24h')->everyThirtyMinutes();
$schedule->command('skinbase:recalculate-trending --period=7d --skip-index')->everyThirtyMinutes()->runInBackground();
// ── Ranking system (rank_v1) ────────────────────────────────────────
// Step 1: compute per-artwork scores every hour at :05
$schedule->job(new RankComputeArtworkScoresJob)->hourlyAt(5)->runInBackground();
// Step 2: build ranked lists every hour at :15 (after scores are ready)
$schedule->job(new RankBuildListsJob)->hourlyAt(15)->withoutOverlapping()->runInBackground();
// ── Ranking Engine V2 — runs every 30 min ──────────────────────────
$schedule->command('nova:recalculate-rankings --sync-rank-scores')
->everyThirtyMinutes()
->name('ranking-v2')
->withoutOverlapping()
->runInBackground();
$schedule->job(new UpdateLeaderboardsJob)
->hourlyAt(20)
->name('leaderboards-refresh')
->withoutOverlapping()
->runInBackground();
$schedule->job(new RebuildTrendingNovaCardsJob)
->hourlyAt(25)
->name('nova-cards-trending-refresh')
->withoutOverlapping()
->runInBackground();
// ── Rising Engine (Heat / Momentum) ─────────────────────────────────
// Step 1: snapshot metric totals every hour at :00
$schedule->command('nova:metrics-snapshot-hourly')
->hourly()
->name('metrics-snapshot-hourly')
->withoutOverlapping()
->runInBackground();
// Step 2: recalculate heat scores every 15 minutes
$schedule->command('nova:recalculate-heat')
->everyFifteenMinutes()
->name('recalculate-heat')
->withoutOverlapping()
->runInBackground();
// Step 2b: bust Nova Cards v3 rising feed cache to stay in sync
$schedule->job(new RecalculateRisingNovaCardsJob)
->everyFifteenMinutes()
->name('nova-cards-rising-cache-refresh')
->withoutOverlapping()
->runInBackground();
// Step 3: prune old snapshots daily at 04:00
$schedule->command('nova:prune-metric-snapshots --keep-days=7')
->dailyAt('04:00');
$schedule->command('skinbase:sync-countries')
->monthlyOn(1, '03:40')
->name('sync-countries')
->withoutOverlapping()
->runInBackground();
// ── Scheduler health heartbeat ──────────────────────────────────────
// Stamps a Redis key each minute so `health:check --only=scheduler` can
// verify cron is alive. The key expires after 5 minutes so a dead cron
// will naturally cause the check to warn/fail.
$schedule->command('health:tick')
->everyMinute()
->name('health-scheduler-tick');
// The active runtime schedule lives in routes/console.php via bootstrap/app.php.
// Keep the kernel empty so recurring work is not registered twice.
}
/**