- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
328 lines
13 KiB
PHP
328 lines
13 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Framework\Queue\Commands;
|
||
|
||
use App\Framework\Console\ConsoleCommand;
|
||
use App\Framework\Console\ExitCode;
|
||
use App\Framework\Core\ValueObjects\Duration;
|
||
use App\Framework\Queue\Services\JobCleanupService;
|
||
use App\Framework\Queue\Services\JobMemoryManager;
|
||
use App\Framework\Performance\MemoryMonitor;
|
||
|
||
final readonly class JobCleanupCommands
|
||
{
|
||
public function __construct(
|
||
private JobCleanupService $cleanupService,
|
||
private JobMemoryManager $memoryManager,
|
||
private MemoryMonitor $memoryMonitor
|
||
) {}
|
||
|
||
#[ConsoleCommand(name: 'queue:cleanup:all', description: 'Run comprehensive queue cleanup with default retention periods')]
|
||
public function runComprehensiveCleanup(): ExitCode
|
||
{
|
||
echo "🧹 Starting Comprehensive Queue Cleanup\n\n";
|
||
|
||
try {
|
||
// Show current memory status
|
||
$memorySummary = $this->memoryMonitor->getSummary();
|
||
echo "💾 Memory Status:\n";
|
||
echo " Current: {$memorySummary->getCurrentHumanReadable()}\n";
|
||
echo " Available: {$memorySummary->getAvailableMemory()->toHumanReadable()}\n";
|
||
echo " Usage: {$memorySummary->getUsagePercentageFormatted()}\n\n";
|
||
|
||
// Show cleanup statistics
|
||
echo "📊 Cleanup Statistics:\n";
|
||
$stats = $this->cleanupService->getCleanupStatistics();
|
||
|
||
echo " Eligible for cleanup:\n";
|
||
echo " • Completed jobs: " . number_format($stats['eligible_completed_jobs']) . " (>{$stats['retention_days']['completed_jobs']} days)\n";
|
||
echo " • Failed jobs: " . number_format($stats['eligible_failed_jobs']) . " (>{$stats['retention_days']['failed_jobs']} days)\n";
|
||
echo " • Job metrics: " . number_format($stats['eligible_metrics']) . " (>{$stats['retention_days']['metrics']} days)\n";
|
||
echo " • Dead letter jobs: " . number_format($stats['eligible_dead_letter_jobs']) . " (>{$stats['retention_days']['dead_letter_jobs']} days)\n";
|
||
echo " • Total eligible: " . number_format($stats['total_eligible']) . "\n";
|
||
echo " • Estimated time: ~{$stats['estimated_cleanup_minutes']} minutes\n\n";
|
||
|
||
if ($stats['total_eligible'] === 0) {
|
||
echo "✅ No data eligible for cleanup\n";
|
||
return ExitCode::SUCCESS;
|
||
}
|
||
|
||
echo "🔄 Starting cleanup process...\n\n";
|
||
|
||
// Run comprehensive cleanup
|
||
$results = $this->cleanupService->runComprehensiveCleanup();
|
||
|
||
// Display results
|
||
echo "✅ Cleanup Results:\n";
|
||
echo " • Completed jobs deleted: " . number_format($results['completed_jobs']) . "\n";
|
||
echo " • Failed jobs deleted: " . number_format($results['failed_jobs']) . "\n";
|
||
echo " • Job metrics deleted: " . number_format($results['job_metrics']) . "\n";
|
||
echo " • Dead letter jobs deleted: " . number_format($results['dead_letter_jobs']) . "\n";
|
||
echo " • Total deleted: " . number_format($results['total_deleted']) . "\n\n";
|
||
|
||
echo "⏱️ Performance:\n";
|
||
echo " • Duration: {$results['duration_seconds']} seconds\n";
|
||
echo " • Memory used: {$results['memory_used']}\n";
|
||
echo " • Peak memory: {$results['memory_peak']}\n\n";
|
||
|
||
if (!empty($results['errors'])) {
|
||
echo "⚠️ Errors occurred:\n";
|
||
foreach ($results['errors'] as $error) {
|
||
echo " • {$error}\n";
|
||
}
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
|
||
echo "✅ Cleanup completed successfully!\n";
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:cleanup:completed', description: 'Clean up completed jobs older than specified days')]
|
||
public function cleanupCompletedJobs(int $days = 30): ExitCode
|
||
{
|
||
echo "🧹 Cleaning Completed Jobs\n\n";
|
||
|
||
try {
|
||
if ($days < 1) {
|
||
echo "❌ Days must be at least 1\n";
|
||
return ExitCode::INVALID_ARGUMENT;
|
||
}
|
||
|
||
echo "📊 Configuration:\n";
|
||
echo " • Delete completed jobs older than: {$days} days\n\n";
|
||
|
||
$duration = Duration::fromDays($days);
|
||
$deleted = $this->cleanupService->cleanupCompletedJobs($duration);
|
||
|
||
echo "✅ Cleanup Results:\n";
|
||
echo " • Completed jobs deleted: " . number_format($deleted) . "\n";
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:cleanup:failed', description: 'Clean up failed jobs older than specified days')]
|
||
public function cleanupFailedJobs(int $days = 90): ExitCode
|
||
{
|
||
echo "🧹 Cleaning Failed Jobs\n\n";
|
||
|
||
try {
|
||
if ($days < 1) {
|
||
echo "❌ Days must be at least 1\n";
|
||
return ExitCode::INVALID_ARGUMENT;
|
||
}
|
||
|
||
echo "📊 Configuration:\n";
|
||
echo " • Delete failed jobs older than: {$days} days\n\n";
|
||
|
||
$duration = Duration::fromDays($days);
|
||
$deleted = $this->cleanupService->cleanupFailedJobs($duration);
|
||
|
||
echo "✅ Cleanup Results:\n";
|
||
echo " • Failed jobs deleted: " . number_format($deleted) . "\n";
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:cleanup:metrics', description: 'Clean up job metrics older than specified days')]
|
||
public function cleanupMetrics(int $days = 180): ExitCode
|
||
{
|
||
echo "🧹 Cleaning Job Metrics\n\n";
|
||
|
||
try {
|
||
if ($days < 1) {
|
||
echo "❌ Days must be at least 1\n";
|
||
return ExitCode::INVALID_ARGUMENT;
|
||
}
|
||
|
||
echo "📊 Configuration:\n";
|
||
echo " • Delete metrics older than: {$days} days\n\n";
|
||
|
||
$duration = Duration::fromDays($days);
|
||
$deleted = $this->cleanupService->cleanupJobMetrics($duration);
|
||
|
||
echo "✅ Cleanup Results:\n";
|
||
echo " • Job metrics deleted: " . number_format($deleted) . "\n";
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:cleanup:deadletter', description: 'Clean up dead letter jobs older than specified days')]
|
||
public function cleanupDeadLetterJobs(int $days = 365): ExitCode
|
||
{
|
||
echo "🧹 Cleaning Dead Letter Jobs\n\n";
|
||
|
||
try {
|
||
if ($days < 1) {
|
||
echo "❌ Days must be at least 1\n";
|
||
return ExitCode::INVALID_ARGUMENT;
|
||
}
|
||
|
||
echo "📊 Configuration:\n";
|
||
echo " • Delete dead letter jobs older than: {$days} days\n\n";
|
||
|
||
$duration = Duration::fromDays($days);
|
||
$deleted = $this->cleanupService->cleanupDeadLetterJobs($duration);
|
||
|
||
echo "✅ Cleanup Results:\n";
|
||
echo " • Dead letter jobs deleted: " . number_format($deleted) . "\n";
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:cleanup:stats', description: 'Show cleanup statistics without performing cleanup')]
|
||
public function showCleanupStatistics(): ExitCode
|
||
{
|
||
echo "📊 Queue Cleanup Statistics\n\n";
|
||
|
||
try {
|
||
$stats = $this->cleanupService->getCleanupStatistics();
|
||
|
||
echo "📋 Retention Periods:\n";
|
||
echo " • Completed jobs: {$stats['retention_days']['completed_jobs']} days\n";
|
||
echo " • Failed jobs: {$stats['retention_days']['failed_jobs']} days\n";
|
||
echo " • Job metrics: {$stats['retention_days']['metrics']} days\n";
|
||
echo " • Dead letter jobs: {$stats['retention_days']['dead_letter_jobs']} days\n\n";
|
||
|
||
echo "🗑️ Eligible for Cleanup:\n";
|
||
echo " • Completed jobs: " . number_format($stats['eligible_completed_jobs']) . "\n";
|
||
echo " • Failed jobs: " . number_format($stats['eligible_failed_jobs']) . "\n";
|
||
echo " • Job metrics: " . number_format($stats['eligible_metrics']) . "\n";
|
||
echo " • Dead letter jobs: " . number_format($stats['eligible_dead_letter_jobs']) . "\n";
|
||
echo " • Total eligible: " . number_format($stats['total_eligible']) . "\n\n";
|
||
|
||
echo "⏱️ Estimated Cleanup Time: ~{$stats['estimated_cleanup_minutes']} minutes\n\n";
|
||
|
||
// Memory recommendations
|
||
$recommendations = $this->memoryManager->getMemoryRecommendations();
|
||
echo "💾 Memory Recommendations:\n";
|
||
echo " • Current usage: {$recommendations['current_usage']}\n";
|
||
echo " • Available memory: {$recommendations['available']}\n";
|
||
echo " • Priority: {$recommendations['priority']}\n";
|
||
|
||
foreach ($recommendations['recommendations'] as $rec) {
|
||
echo "\n 📌 {$rec['type']}:\n";
|
||
echo " {$rec['message']}\n";
|
||
if (!empty($rec['actions'])) {
|
||
echo " Actions:\n";
|
||
foreach ($rec['actions'] as $action) {
|
||
echo " • {$action}\n";
|
||
}
|
||
}
|
||
}
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:memory:status', description: 'Show current memory status and recommendations')]
|
||
public function showMemoryStatus(): ExitCode
|
||
{
|
||
echo "💾 Queue Memory Status\n\n";
|
||
|
||
try {
|
||
// Get memory snapshot
|
||
$snapshot = $this->memoryManager->getJobMemorySnapshot('memory_status_check');
|
||
|
||
echo "📊 Current Memory Usage:\n";
|
||
echo " • Current: {$snapshot['current']} ({$snapshot['usage_percentage']}%)\n";
|
||
echo " • Peak: {$snapshot['peak']}\n";
|
||
echo " • Limit: {$snapshot['limit']}\n";
|
||
echo " • Available: {$snapshot['available']}\n";
|
||
echo " • Status: {$snapshot['status']}\n\n";
|
||
|
||
// Status indicators
|
||
if ($snapshot['is_critical']) {
|
||
echo "🔴 CRITICAL: Memory usage is critically high!\n\n";
|
||
} elseif ($snapshot['is_warning']) {
|
||
echo "🟡 WARNING: Memory usage is elevated.\n\n";
|
||
} else {
|
||
echo "🟢 NORMAL: Memory usage is within acceptable limits.\n\n";
|
||
}
|
||
|
||
// Get recommendations
|
||
$recommendations = $this->memoryManager->getMemoryRecommendations();
|
||
|
||
echo "📌 Recommendations:\n";
|
||
foreach ($recommendations['recommendations'] as $rec) {
|
||
echo "\n {$rec['type']}:\n";
|
||
echo " {$rec['message']}\n";
|
||
if (!empty($rec['actions'])) {
|
||
echo " Suggested actions:\n";
|
||
foreach ($rec['actions'] as $action) {
|
||
echo " • {$action}\n";
|
||
}
|
||
}
|
||
}
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
|
||
#[ConsoleCommand(name: 'queue:memory:optimize', description: 'Optimize memory for job processing')]
|
||
public function optimizeMemory(): ExitCode
|
||
{
|
||
echo "🔧 Optimizing Queue Memory\n\n";
|
||
|
||
try {
|
||
echo "📊 Before Optimization:\n";
|
||
$beforeSnapshot = $this->memoryManager->getJobMemorySnapshot('before_optimization');
|
||
echo " • Memory: {$beforeSnapshot['current']} ({$beforeSnapshot['usage_percentage']}%)\n\n";
|
||
|
||
echo "🔄 Running optimization...\n";
|
||
$optimization = $this->memoryManager->optimizeForJob('manual_optimization');
|
||
|
||
echo "\n📊 After Optimization:\n";
|
||
echo " • Memory: {$optimization['after']}\n";
|
||
echo " • Freed: {$optimization['freed']}\n";
|
||
echo " • Usage before: {$optimization['usage_before']}\n";
|
||
echo " • Usage after: {$optimization['usage_after']}\n\n";
|
||
|
||
if ($optimization['freed_bytes'] > 0) {
|
||
echo "✅ Successfully freed {$optimization['freed']} of memory\n";
|
||
} else {
|
||
echo "ℹ️ No significant memory was freed (system may have already been optimized)\n";
|
||
}
|
||
|
||
return ExitCode::SUCCESS;
|
||
|
||
} catch (\Exception $e) {
|
||
echo "❌ Error: {$e->getMessage()}\n";
|
||
return ExitCode::GENERAL_ERROR;
|
||
}
|
||
}
|
||
} |