Wire admin studio SSR and search infrastructure
This commit is contained in:
@@ -18,14 +18,14 @@ Artisan::command('uploads:cleanup {--limit=100 : Maximum drafts to clean in one
|
||||
|
||||
// ── Scheduled tasks ────────────────────────────────────────────────────────────
|
||||
|
||||
// Recalculate trending scores every 30 minutes (staggered: 24h first, then 7d)
|
||||
// Recalculate trending scores every 30 minutes, staggered away from other hot paths.
|
||||
Schedule::command('skinbase:recalculate-trending --period=24h')
|
||||
->everyThirtyMinutes()
|
||||
->cron('6,36 * * * *')
|
||||
->name('trending-24h')
|
||||
->withoutOverlapping();
|
||||
|
||||
Schedule::command('skinbase:recalculate-trending --period=7d --skip-index')
|
||||
->everyThirtyMinutes()
|
||||
->cron('19,49 * * * *')
|
||||
->name('trending-7d')
|
||||
->runInBackground()
|
||||
->withoutOverlapping();
|
||||
@@ -39,7 +39,7 @@ Schedule::command('skinbase:reset-windowed-stats --period=24h')
|
||||
->withoutOverlapping();
|
||||
|
||||
Schedule::command('skinbase:reset-windowed-stats --period=7d')
|
||||
->weeklyOn(1, '03:30') // Monday 03:30
|
||||
->weeklyOn(1, '03:50') // Monday 03:50
|
||||
->name('reset-windowed-stats-7d')
|
||||
->withoutOverlapping();
|
||||
|
||||
@@ -48,11 +48,12 @@ Schedule::command('uploads:cleanup')->dailyAt('03:00');
|
||||
Schedule::command('analytics:aggregate-similar-artworks')->dailyAt('03:10');
|
||||
Schedule::command('analytics:aggregate-feed')->dailyAt('03:20');
|
||||
Schedule::command('analytics:aggregate-discovery-feedback')->dailyAt('03:25');
|
||||
Schedule::command('analytics:aggregate-tag-interactions')->dailyAt('03:35');
|
||||
|
||||
// Drain Redis artwork-stat delta queue so MySQL counters stay fresh.
|
||||
// Run every 5 minutes with overlap protection.
|
||||
// Offset this off the :00/:10 boundaries so it does not pile onto publish jobs.
|
||||
Schedule::command('skinbase:flush-redis-stats')
|
||||
->everyFiveMinutes()
|
||||
->cron('1,11,21,31,41,51 * * * *')
|
||||
->name('flush-redis-stats')
|
||||
->withoutOverlapping();
|
||||
|
||||
@@ -116,21 +117,29 @@ Schedule::command('nova-cards:publish-scheduled')
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('collections:sync-lifecycle')
|
||||
->everyTenMinutes()
|
||||
->cron('3,13,23,33,43,53 * * * *')
|
||||
->name('sync-collection-lifecycle')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('homepage:warm-guest-cache')
|
||||
->everyTenMinutes()
|
||||
->cron('5,15,25,35,45,55 * * * *')
|
||||
->name('warm-homepage-guest-cache')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
// Safety-net audit for Meilisearch drift on recently touched artworks.
|
||||
// Scans the last 65 minutes to cover the previous hour plus a small buffer.
|
||||
Schedule::command('artworks:search-reconcile --repair --reverse --remove-unexpected --limit=1000 --recent-minutes=65')
|
||||
->hourlyAt(28)
|
||||
->name('artworks-search-reconcile-recent')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
// ── Feed 2.0: Trending Cache Warm-up ─────────────────────────────────────────
|
||||
// Warm the post trending cache every 2 minutes (complements the 2-min TTL).
|
||||
// Warm the post trending cache every 2 minutes on odd minutes to avoid :00/:10 pileups.
|
||||
Schedule::command('posts:warm-trending')
|
||||
->everyTwoMinutes()
|
||||
->cron('1-59/2 * * * *')
|
||||
->name('warm-post-trending')
|
||||
->withoutOverlapping();
|
||||
|
||||
@@ -138,7 +147,7 @@ Schedule::command('posts:warm-trending')
|
||||
// Recalculate ranking_score + engagement_velocity every 30 minutes.
|
||||
// Also syncs V2 scores to rank_artwork_scores so list builds benefit.
|
||||
Schedule::command('nova:recalculate-rankings --sync-rank-scores')
|
||||
->everyThirtyMinutes()
|
||||
->cron('7,37 * * * *')
|
||||
->name('ranking-v2')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
@@ -146,21 +155,30 @@ Schedule::command('nova:recalculate-rankings --sync-rank-scores')
|
||||
// ── Rising Engine (Heat / Momentum) ───────────────────────────────────────────
|
||||
// Snapshot current totals each hour, then recalculate heat every 15 minutes.
|
||||
Schedule::command('nova:metrics-snapshot-hourly')
|
||||
->hourly()
|
||||
->hourlyAt(2)
|
||||
->name('metrics-snapshot-hourly')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('nova:recalculate-heat')
|
||||
->everyFifteenMinutes()
|
||||
->cron('9,24,39,54 * * * *')
|
||||
->name('recalculate-heat')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
// Additional production schedules that must live here because Laravel 11's
|
||||
// active scheduler in this app is defined in routes/console.php, not Kernel.
|
||||
|
||||
// Generate static sitemap XML files that nginx can serve directly without PHP.
|
||||
// The generate command writes public/sitemap.xml + public/sitemaps/{name}.xml.
|
||||
Schedule::command('skinbase:sitemaps:generate')
|
||||
->dailyAt('22:30')
|
||||
->name('sitemaps-generate')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('skinbase:sitemaps:publish --sync')
|
||||
->everySixHours()
|
||||
->cron('8 */6 * * *')
|
||||
->name('sitemaps-publish')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
@@ -171,13 +189,15 @@ Schedule::command('skinbase:sitemaps:validate')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
// Keep the old release-pipeline cleanup running so stale release artifacts are pruned.
|
||||
|
||||
Schedule::job(new \App\Jobs\Sitemaps\CleanupSitemapReleasesJob())
|
||||
->dailyAt('05:00')
|
||||
->name('sitemaps-cleanup')
|
||||
->withoutOverlapping();
|
||||
|
||||
Schedule::command('collections:dispatch-maintenance')
|
||||
->hourly()
|
||||
->hourlyAt(43)
|
||||
->name('dispatch-collection-maintenance')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
@@ -202,7 +222,7 @@ Schedule::job(new \App\Jobs\RebuildTrendingNovaCardsJob())
|
||||
->withoutOverlapping();
|
||||
|
||||
Schedule::job(new \App\Jobs\RecalculateRisingNovaCardsJob())
|
||||
->everyFifteenMinutes()
|
||||
->cron('12,27,42,57 * * * *')
|
||||
->name('nova-cards-rising-cache-refresh')
|
||||
->withoutOverlapping();
|
||||
|
||||
@@ -223,30 +243,30 @@ Schedule::command('health:tick')
|
||||
->withoutOverlapping();
|
||||
|
||||
Schedule::command('forum:ai-scan')
|
||||
->everyTenMinutes()
|
||||
->hourlyAt(16)
|
||||
->name('forum-ai-scan')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('forum:bot-scan')
|
||||
->everyFiveMinutes()
|
||||
->hourlyAt(22)
|
||||
->name('forum-bot-scan')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('forum:scan-posts --limit=250')
|
||||
->everyFifteenMinutes()
|
||||
->hourlyAt(17)
|
||||
->name('forum-post-scan')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('forum:firewall-scan')
|
||||
->everyFiveMinutes()
|
||||
->hourlyAt(40)
|
||||
->name('forum-firewall-scan')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('horizon:snapshot')
|
||||
->everyFiveMinutes()
|
||||
->hourlyAt(45)
|
||||
->name('horizon-snapshot')
|
||||
->withoutOverlapping();
|
||||
|
||||
Reference in New Issue
Block a user