New_Micro_Learning/backend/routes/console.php

61 خطوط
2.9 KiB
PHP

<?php
use App\Modules\Collaboration\Application\NotificationOrchestrator;
use App\Modules\Courses\Domain\CourseVersion;
use App\Modules\Courses\Domain\Enums\CourseVersionStatus;
use App\Modules\Publishing\Application\CoursePublication;
use App\Modules\System\Application\QueueHeartbeat;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schedule;
use Illuminate\Support\Facades\Storage;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Artisan::command('learning:process-schedules', function (CoursePublication $publication) {
$published = 0;
$unpublished = 0;
CourseVersion::query()->where('status', CourseVersionStatus::InReview)->whereNotNull('scheduled_publish_at')->where('scheduled_publish_at', '<=', now())->each(function (CourseVersion $version) use ($publication, &$published) {
$publication->publish($version);
$published++;
});
CourseVersion::query()->where('status', CourseVersionStatus::Published)->whereNull('unpublished_at')->whereNotNull('scheduled_unpublish_at')->where('scheduled_unpublish_at', '<=', now())->each(function (CourseVersion $version) use ($publication, &$unpublished) {
$publication->unpublish($version);
$unpublished++;
});
$this->info("Published {$published}; unpublished {$unpublished}.");
})->purpose('Process scheduled course publication lifecycle');
Schedule::command('learning:process-schedules')->everyMinute()->withoutOverlapping();
Artisan::command('notifications:process-schedules', function (NotificationOrchestrator $notifications) {
$result = $notifications->deliverDue();
$this->info("Notification schedules: {$result['sent']} sent, {$result['skipped']} skipped, {$result['failed']} failed.");
})->purpose('Deliver due in-app notification schedules');
Schedule::command('notifications:process-schedules')->everyMinute()->withoutOverlapping();
Artisan::command('system:heartbeat', function () {
Cache::put('system:scheduler-heartbeat', now(), now()->addMinutes(5));
$this->info('Scheduler heartbeat recorded.');
});
Artisan::command('exports:prune', function () {
$cutoff = now()->subDays((int) config('exports.retention_days', 30));
DB::table('export_jobs')->where('created_at', '<', $cutoff)->whereIn('status', ['completed', 'failed', 'cancelled'])->orderBy('created_at')->each(function ($row): void {
if ($row->path && $row->disk) {
Storage::disk($row->disk)->delete($row->path);
}
DB::table('export_jobs')->where('id', $row->id)->delete();
});
$this->info('Expired export artifacts pruned.');
});
Schedule::command('system:heartbeat')->everyMinute();
Schedule::job(new QueueHeartbeat)->everyMinute()->withoutOverlapping();
Schedule::command('exports:prune')->dailyAt('02:30')->withoutOverlapping();