110 lines
4.9 KiB
PHP
110 lines
4.9 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Services\Ollama\OllamaService;
|
||
use App\Services\Qdrant\QdrantService;
|
||
use Illuminate\Console\Command;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
/**
|
||
* php artisan kb:health-check
|
||
*
|
||
* Semak status semua perkhidmatan yang diperlukan.
|
||
*/
|
||
class HealthCheckCommand extends Command
|
||
{
|
||
protected $signature = 'kb:health-check';
|
||
protected $description = 'Semak status Ollama, Qdrant, dan MySQL';
|
||
|
||
public function handle(OllamaService $ollama, QdrantService $qdrant): int
|
||
{
|
||
$this->info('════════════════════════════════════════');
|
||
$this->info(' PEMERIKSAAN KESIHATAN SISTEM');
|
||
$this->info('════════════════════════════════════════');
|
||
|
||
$allOk = true;
|
||
|
||
// ── MySQL ─────────────────────────────────────────────────────────
|
||
$this->line('');
|
||
$this->info('📦 MySQL');
|
||
try {
|
||
DB::connection()->getPdo();
|
||
$dbName = DB::getDatabaseName();
|
||
$this->line(" ✅ Berjaya sambung ke: {$dbName}");
|
||
} catch (\Exception $e) {
|
||
$this->error(" ❌ Tidak dapat sambung: {$e->getMessage()}");
|
||
$allOk = false;
|
||
}
|
||
|
||
// ── Ollama ────────────────────────────────────────────────────────
|
||
$this->line('');
|
||
$this->info('🤖 Ollama');
|
||
$ollamaStatus = $ollama->healthCheck();
|
||
|
||
if ($ollamaStatus['online']) {
|
||
$this->line(" ✅ Online");
|
||
$chatOk = $ollamaStatus['chat_model'] ? '✅' : '❌';
|
||
$embedOk = $ollamaStatus['embed_model'] ? '✅' : '❌';
|
||
$this->line(" {$chatOk} Model Chat: " . config('ollama.chat_model'));
|
||
$this->line(" {$embedOk} Model Embed: " . config('ollama.embedding_model'));
|
||
|
||
if (!$ollamaStatus['chat_model'] || !$ollamaStatus['embed_model']) {
|
||
$allOk = false;
|
||
}
|
||
} else {
|
||
$this->error(" ❌ Offline");
|
||
if ($ollamaStatus['error']) {
|
||
$this->line(" " . $ollamaStatus['error']);
|
||
}
|
||
$allOk = false;
|
||
}
|
||
|
||
// ── Qdrant ────────────────────────────────────────────────────────
|
||
$this->line('');
|
||
$this->info('🗄️ Qdrant');
|
||
$qdrantStatus = $qdrant->healthCheck();
|
||
|
||
if ($qdrantStatus['online']) {
|
||
$this->line(" ✅ Online");
|
||
$collOk = $qdrantStatus['collection_exists'] ? '✅' : '⚠️ ';
|
||
$this->line(" {$collOk} Collection: " . config('qdrant.collection'));
|
||
if ($qdrantStatus['collection_exists']) {
|
||
$this->line(" 📊 Vectors: " . number_format($qdrantStatus['points_count'] ?? 0));
|
||
} else {
|
||
$this->warn(" Collection belum wujud. Akan dibuat secara automatik semasa pertama embed.");
|
||
}
|
||
} else {
|
||
$this->error(" ❌ Offline");
|
||
if ($qdrantStatus['error']) {
|
||
$this->line(" " . $qdrantStatus['error']);
|
||
}
|
||
$allOk = false;
|
||
}
|
||
|
||
// ── Queue ─────────────────────────────────────────────────────────
|
||
$this->line('');
|
||
$this->info('⏳ Queue');
|
||
$driver = config('queue.default');
|
||
$this->line(" ℹ️ Driver: {$driver}");
|
||
if ($driver === 'sync') {
|
||
$this->warn(" ⚠️ Queue driver adalah 'sync' — job akan dijalankan secara synchronous.");
|
||
$this->warn(" Tukar kepada 'database' atau 'redis' untuk production.");
|
||
} else {
|
||
$this->line(" ✅ Driver konfigurasi untuk async.");
|
||
}
|
||
|
||
// ── Ringkasan ─────────────────────────────────────────────────────
|
||
$this->line('');
|
||
$this->info('════════════════════════════════════════');
|
||
if ($allOk) {
|
||
$this->info(' ✅ SEMUA PERKHIDMATAN OK');
|
||
} else {
|
||
$this->error(' ❌ ADA PERKHIDMATAN YANG BERMASALAH');
|
||
}
|
||
$this->info('════════════════════════════════════════');
|
||
|
||
return $allOk ? self::SUCCESS : self::FAILURE;
|
||
}
|
||
}
|