Files
easystream-main/f_jobs/CleanupJob.php
SamiAhmed7777 0b7e2d0a5b feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
2025-10-21 00:39:45 -07:00

450 lines
14 KiB
PHP

<?php
/*******************************************************************************************************************
| System Cleanup Job
| Handles automated system maintenance and cleanup tasks
|*******************************************************************************************************************/
class CleanupJob extends BaseJob
{
private $queueManager;
public function __construct()
{
parent::__construct();
$this->queueManager = new VQueueManager();
}
/**
* Handle cleanup job
* @param array $data Cleanup configuration data
* @return array Cleanup result
*/
public function handle($data)
{
$cleanupType = $data['type'] ?? 'full';
$this->logProgress('Starting system cleanup', [
'type' => $cleanupType,
'data' => $data
]);
$results = [];
try {
switch ($cleanupType) {
case 'full':
$results = $this->performFullCleanup($data);
break;
case 'logs':
$results['logs'] = $this->cleanupLogs($data);
break;
case 'temp_files':
$results['temp_files'] = $this->cleanupTempFiles($data);
break;
case 'old_sessions':
$results['sessions'] = $this->cleanupOldSessions($data);
break;
case 'failed_uploads':
$results['failed_uploads'] = $this->cleanupFailedUploads($data);
break;
case 'analytics':
$results['analytics'] = $this->cleanupOldAnalytics($data);
break;
default:
throw new Exception("Unknown cleanup type: {$cleanupType}");
}
$this->logProgress('System cleanup completed', [
'type' => $cleanupType,
'results' => $results
]);
return [
'success' => true,
'type' => $cleanupType,
'results' => $results,
'message' => 'Cleanup completed successfully'
];
} catch (Exception $e) {
$this->logError('System cleanup failed', [
'type' => $cleanupType,
'error' => $e->getMessage()
]);
throw $e;
}
}
/**
* Perform full system cleanup
* @param array $data Configuration data
* @return array Cleanup results
*/
private function performFullCleanup($data)
{
$results = [];
$this->updateProgress(1, 8, 'Cleaning up logs');
$results['logs'] = $this->cleanupLogs($data);
$this->updateProgress(2, 8, 'Cleaning up temporary files');
$results['temp_files'] = $this->cleanupTempFiles($data);
$this->updateProgress(3, 8, 'Cleaning up old sessions');
$results['sessions'] = $this->cleanupOldSessions($data);
$this->updateProgress(4, 8, 'Cleaning up failed uploads');
$results['failed_uploads'] = $this->cleanupFailedUploads($data);
$this->updateProgress(5, 8, 'Cleaning up old analytics');
$results['analytics'] = $this->cleanupOldAnalytics($data);
$this->updateProgress(6, 8, 'Cleaning up queue jobs');
$results['queue_jobs'] = $this->queueManager->cleanupOldJobs(
$data['queue_retention_hours'] ?? 24
);
$this->updateProgress(7, 8, 'Cleaning up orphaned files');
$results['orphaned_files'] = $this->cleanupOrphanedFiles($data);
$this->updateProgress(8, 8, 'Optimizing database');
$results['database'] = $this->optimizeDatabase($data);
return $results;
}
/**
* Cleanup old log files
* @param array $data Configuration data
* @return array Cleanup result
*/
private function cleanupLogs($data)
{
$logDir = _FPATH . 'f_data/logs/';
$retentionDays = $data['log_retention_days'] ?? 30;
$cutoffTime = time() - ($retentionDays * 24 * 3600);
$deletedFiles = 0;
$deletedSize = 0;
if (is_dir($logDir)) {
$files = glob($logDir . '*.log');
foreach ($files as $file) {
if (filemtime($file) < $cutoffTime) {
$size = filesize($file);
if (unlink($file)) {
$deletedFiles++;
$deletedSize += $size;
}
}
}
}
return [
'deleted_files' => $deletedFiles,
'deleted_size' => $deletedSize,
'retention_days' => $retentionDays
];
}
/**
* Cleanup temporary files
* @param array $data Configuration data
* @return array Cleanup result
*/
private function cleanupTempFiles($data)
{
$tempDir = _FPATH . 'f_data/temp/';
$maxAge = $data['temp_file_max_age_hours'] ?? 24;
$cutoffTime = time() - ($maxAge * 3600);
$deletedFiles = 0;
$deletedSize = 0;
if (is_dir($tempDir)) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $file) {
if ($file->isFile() && $file->getMTime() < $cutoffTime) {
$size = $file->getSize();
if (unlink($file->getPathname())) {
$deletedFiles++;
$deletedSize += $size;
}
}
}
}
return [
'deleted_files' => $deletedFiles,
'deleted_size' => $deletedSize,
'max_age_hours' => $maxAge
];
}
/**
* Cleanup old sessions
* @param array $data Configuration data
* @return array Cleanup result
*/
private function cleanupOldSessions($data)
{
$maxAge = $data['session_max_age_hours'] ?? 168; // 7 days
$cutoffTime = date('Y-m-d H:i:s', time() - ($maxAge * 3600));
try {
$db = $this->getDatabase();
// Cleanup database sessions if using database session storage
$query = "DELETE FROM db_sessions WHERE last_activity < ?";
$db->doQuery($query, [$cutoffTime]);
$deletedSessions = $db->getAffectedRows();
return [
'deleted_db_sessions' => $deletedSessions,
'max_age_hours' => $maxAge
];
} catch (Exception $e) {
$this->logError('Session cleanup failed', [
'error' => $e->getMessage()
]);
return [
'error' => $e->getMessage(),
'deleted_db_sessions' => 0
];
}
}
/**
* Cleanup failed uploads
* @param array $data Configuration data
* @return array Cleanup result
*/
private function cleanupFailedUploads($data)
{
$maxAge = $data['failed_upload_max_age_hours'] ?? 48;
$cutoffTime = date('Y-m-d H:i:s', time() - ($maxAge * 3600));
try {
$db = $this->getDatabase();
// Find failed uploads
$query = "SELECT file_key, usr_id FROM db_videofiles
WHERE processing_status = 'failed'
AND processed_at < ?";
$result = $db->doQuery($query, [$cutoffTime]);
$deletedRecords = 0;
$deletedFiles = 0;
$deletedSize = 0;
while ($row = $db->doFetch($result)) {
// Delete associated files
$userDir = _FPATH . 'f_data/media/' . $row['usr_id'] . '/';
$videoFiles = glob($userDir . $row['file_key'] . '*');
foreach ($videoFiles as $file) {
if (is_file($file)) {
$deletedSize += filesize($file);
if (unlink($file)) {
$deletedFiles++;
}
}
}
// Delete database record
$deleteQuery = "DELETE FROM db_videofiles WHERE file_key = ?";
$db->doQuery($deleteQuery, [$row['file_key']]);
$deletedRecords++;
}
return [
'deleted_records' => $deletedRecords,
'deleted_files' => $deletedFiles,
'deleted_size' => $deletedSize,
'max_age_hours' => $maxAge
];
} catch (Exception $e) {
$this->logError('Failed upload cleanup failed', [
'error' => $e->getMessage()
]);
return [
'error' => $e->getMessage(),
'deleted_records' => 0,
'deleted_files' => 0
];
}
}
/**
* Cleanup old analytics data
* @param array $data Configuration data
* @return array Cleanup result
*/
private function cleanupOldAnalytics($data)
{
$retentionDays = $data['analytics_retention_days'] ?? 90;
$cutoffTime = date('Y-m-d H:i:s', time() - ($retentionDays * 24 * 3600));
try {
$db = $this->getDatabase();
$deletedRecords = 0;
// Cleanup video analytics
$query = "DELETE FROM db_video_analytics WHERE created_at < ?";
$db->doQuery($query, [$cutoffTime]);
$deletedRecords += $db->getAffectedRows();
// Cleanup video views
$query = "DELETE FROM db_video_views WHERE created_at < ?";
$db->doQuery($query, [$cutoffTime]);
$deletedRecords += $db->getAffectedRows();
return [
'deleted_records' => $deletedRecords,
'retention_days' => $retentionDays
];
} catch (Exception $e) {
$this->logError('Analytics cleanup failed', [
'error' => $e->getMessage()
]);
return [
'error' => $e->getMessage(),
'deleted_records' => 0
];
}
}
/**
* Cleanup orphaned files
* @param array $data Configuration data
* @return array Cleanup result
*/
private function cleanupOrphanedFiles($data)
{
$mediaDir = _FPATH . 'f_data/media/';
$deletedFiles = 0;
$deletedSize = 0;
try {
if (!is_dir($mediaDir)) {
return [
'deleted_files' => 0,
'deleted_size' => 0,
'message' => 'Media directory not found'
];
}
// Get all file keys from database
$db = $this->getDatabase();
$query = "SELECT file_key FROM db_videofiles
UNION SELECT file_key FROM db_imagefiles
UNION SELECT file_key FROM db_audiofiles
UNION SELECT file_key FROM db_documentfiles";
$result = $db->doQuery($query);
$validKeys = [];
while ($row = $db->doFetch($result)) {
$validKeys[] = $row['file_key'];
}
// Scan media directory for orphaned files
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($mediaDir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $file) {
if ($file->isFile()) {
$filename = $file->getFilename();
// Extract file key from filename (assuming format: filekey.extension)
$fileKey = pathinfo($filename, PATHINFO_FILENAME);
if (!in_array($fileKey, $validKeys)) {
$size = $file->getSize();
if (unlink($file->getPathname())) {
$deletedFiles++;
$deletedSize += $size;
}
}
}
}
return [
'deleted_files' => $deletedFiles,
'deleted_size' => $deletedSize,
'scanned_keys' => count($validKeys)
];
} catch (Exception $e) {
$this->logError('Orphaned files cleanup failed', [
'error' => $e->getMessage()
]);
return [
'error' => $e->getMessage(),
'deleted_files' => 0,
'deleted_size' => 0
];
}
}
/**
* Optimize database
* @param array $data Configuration data
* @return array Optimization result
*/
private function optimizeDatabase($data)
{
try {
$db = $this->getDatabase();
$optimizedTables = 0;
// Get all tables
$query = "SHOW TABLES";
$result = $db->doQuery($query);
while ($row = $db->doFetch($result)) {
$table = array_values($row)[0];
// Optimize table
$optimizeQuery = "OPTIMIZE TABLE `{$table}`";
$db->doQuery($optimizeQuery);
$optimizedTables++;
}
return [
'optimized_tables' => $optimizedTables,
'message' => 'Database optimization completed'
];
} catch (Exception $e) {
$this->logError('Database optimization failed', [
'error' => $e->getMessage()
]);
return [
'error' => $e->getMessage(),
'optimized_tables' => 0
];
}
}
}