![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/private_html/ |
<?php
// Automated script to detect and fix stuck processing tracks
// This can be run as a cron job to ensure all tracks are properly handled
require_once 'config/database.php';
// Configuration
$max_processing_time = 3600; // 1 hour in seconds
$log_file = 'auto_fix_log.txt';
function logMessage($message) {
global $log_file;
$timestamp = date('Y-m-d H:i:s');
$log_entry = "[$timestamp] $message\n";
file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
echo $log_entry;
}
echo "<h1>🤖 Auto-Fix Stuck Tracks</h1>";
$pdo = getDBConnection();
if (!$pdo) {
logMessage("❌ Database connection failed");
exit;
}
// Find tracks stuck in processing for more than 1 hour
$stmt = $pdo->prepare("
SELECT id, task_id, title, status, created_at, updated_at
FROM music_tracks
WHERE status = 'processing'
AND created_at < DATE_SUB(NOW(), INTERVAL ? SECOND)
ORDER BY created_at ASC
");
$stmt->execute([$max_processing_time]);
$stuck_tracks = $stmt->fetchAll();
if (empty($stuck_tracks)) {
logMessage("✅ No stuck processing tracks found");
echo "<p style='color: green;'>✅ No stuck processing tracks found</p>";
} else {
logMessage("⚠️ Found " . count($stuck_tracks) . " stuck processing tracks");
echo "<h2>⚠️ Found " . count($stuck_tracks) . " Stuck Tracks</h2>";
foreach ($stuck_tracks as $track) {
$track_id = $track['id'];
$task_id = $track['task_id'];
$title = $track['title'] ?: 'Untitled Track';
$created_time = strtotime($track['created_at']);
$age_hours = round((time() - $created_time) / 3600, 1);
logMessage("Processing stuck track ID: $track_id, Task: $task_id, Age: {$age_hours}h");
// Try to check API.Box status first
$api_key = '63edba40620216c5aa2c04240ac41dbd';
$api_url = "https://api.api.box/api/v1/status/$task_id";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $api_key,
'Content-Type: application/json',
'User-Agent: SoundStudioPro-AutoFix/1.0'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200 && $response) {
$api_data = json_decode($response, true);
if ($api_data && isset($api_data['status'])) {
$api_status = $api_data['status'];
if ($api_status === 'failed') {
// Track failed in API.Box
$error_msg = $api_data['error'] ?? 'Generation failed';
$error_metadata = [
'code' => 531,
'msg' => $error_msg,
'error_type' => 'generation_failed',
'data' => $api_data,
'timestamp' => date('Y-m-d H:i:s'),
'auto_fixed' => true
];
$update_stmt = $pdo->prepare("
UPDATE music_tracks
SET status = 'failed',
metadata = ?,
updated_at = NOW()
WHERE id = ?
");
if ($update_stmt->execute([json_encode($error_metadata), $track_id])) {
logMessage("✅ Track $track_id marked as failed (API.Box status: failed)");
echo "<p style='color: orange;'>✅ Track $track_id marked as failed (API.Box status: failed)</p>";
} else {
logMessage("❌ Failed to update track $track_id");
echo "<p style='color: red;'>❌ Failed to update track $track_id</p>";
}
} elseif ($api_status === 'completed' && isset($api_data['result']['audio_url'])) {
// Track completed in API.Box
$audio_url = $api_data['result']['audio_url'];
$duration = $api_data['result']['duration'] ?? null;
// Extract title from API response
$api_title = null;
if (isset($api_data['result']['title']) && !empty($api_data['result']['title'])) {
$api_title = trim($api_data['result']['title']);
}
// Also try to get title from saved task_results file
if (!$api_title) {
$result_file = __DIR__ . "/task_results/{$task_id}.json";
if (file_exists($result_file)) {
$result_data = json_decode(file_get_contents($result_file), true);
if (isset($result_data['data']['data']) && is_array($result_data['data']['data'])) {
foreach ($result_data['data']['data'] as $item) {
if (isset($item['title']) && !empty($item['title']) && trim($item['title']) !== '') {
$api_title = trim($item['title']);
break;
}
}
}
}
}
// Only update title if current title is empty or default
$should_update_title = $api_title && (!$title || $title === '' || $title === 'Untitled Track' || $title === 'Generated Track');
$metadata = [
'code' => 200,
'data' => $api_data,
'timestamp' => date('Y-m-d H:i:s'),
'auto_fixed' => true
];
if ($should_update_title) {
$update_stmt = $pdo->prepare("
UPDATE music_tracks
SET status = 'complete',
audio_url = ?,
duration = ?,
title = ?,
metadata = ?,
updated_at = NOW()
WHERE id = ?
");
$execute_result = $update_stmt->execute([$audio_url, $duration, $api_title, json_encode($metadata), $track_id]);
} else {
$update_stmt = $pdo->prepare("
UPDATE music_tracks
SET status = 'complete',
audio_url = ?,
duration = ?,
metadata = ?,
updated_at = NOW()
WHERE id = ?
");
$execute_result = $update_stmt->execute([$audio_url, $duration, json_encode($metadata), $track_id]);
}
if ($execute_result) {
$title_msg = $should_update_title ? " with title: $api_title" : "";
logMessage("✅ Track $track_id marked as complete (API.Box status: completed)$title_msg");
echo "<p style='color: green;'>✅ Track $track_id marked as complete (API.Box status: completed)$title_msg</p>";
} else {
logMessage("❌ Failed to update track $track_id");
echo "<p style='color: red;'>❌ Failed to update track $track_id</p>";
}
} else {
// Still processing or unknown status
logMessage("⚠️ Track $track_id still processing in API.Box (status: $api_status)");
echo "<p style='color: orange;'>⚠️ Track $track_id still processing in API.Box (status: $api_status)</p>";
}
} else {
logMessage("⚠️ Invalid API.Box response for track $track_id");
echo "<p style='color: orange;'>⚠️ Invalid API.Box response for track $track_id</p>";
}
} else {
// API.Box check failed, mark as failed after extended time
if ($age_hours > 2) { // More than 2 hours old
$error_metadata = [
'code' => 531,
'msg' => 'Track generation timeout - API.Box unavailable',
'error_type' => 'timeout',
'data' => ['http_code' => $http_code, 'response' => $response],
'timestamp' => date('Y-m-d H:i:s'),
'auto_fixed' => true
];
$update_stmt = $pdo->prepare("
UPDATE music_tracks
SET status = 'failed',
metadata = ?,
updated_at = NOW()
WHERE id = ?
");
if ($update_stmt->execute([json_encode($error_metadata), $track_id])) {
logMessage("✅ Track $track_id marked as failed (timeout after {$age_hours}h)");
echo "<p style='color: red;'>✅ Track $track_id marked as failed (timeout after {$age_hours}h)</p>";
} else {
logMessage("❌ Failed to update track $track_id");
echo "<p style='color: red;'>❌ Failed to update track $track_id</p>";
}
} else {
logMessage("⚠️ Track $track_id API.Box check failed (HTTP $http_code), but track is only {$age_hours}h old");
echo "<p style='color: orange;'>⚠️ Track $track_id API.Box check failed (HTTP $http_code), but track is only {$age_hours}h old</p>";
}
}
}
}
// PART 2: Fix completed tracks with missing titles
logMessage("Starting missing title fix...");
echo "<h2>🔧 Fixing Missing Titles on Completed Tracks</h2>";
// Only fix titles that haven't been user-modified
$stmt = $pdo->query("
SELECT id, task_id, title FROM music_tracks
WHERE status = 'complete'
AND (title IS NULL OR title = '' OR title = 'Untitled Track' OR title = 'Generated Track')
AND (title_user_modified = 0 OR title_user_modified IS NULL)
ORDER BY created_at DESC
LIMIT 100
");
$missing_title_tracks = $stmt->fetchAll();
$title_fixed_count = 0;
if (empty($missing_title_tracks)) {
logMessage("✅ No completed tracks with missing titles found");
echo "<p style='color: green;'>✅ No completed tracks with missing titles found</p>";
} else {
logMessage("Found " . count($missing_title_tracks) . " completed tracks with missing titles");
echo "<p>Found " . count($missing_title_tracks) . " completed tracks with missing titles</p>";
foreach ($missing_title_tracks as $missing_track) {
$result_file = __DIR__ . "/task_results/{$missing_track['task_id']}.json";
if (file_exists($result_file)) {
$result_data = json_decode(file_get_contents($result_file), true);
// Extract title from API response
$extracted_title = null;
if (isset($result_data['data']['data']) && is_array($result_data['data']['data'])) {
foreach ($result_data['data']['data'] as $item) {
if (isset($item['title']) && !empty($item['title']) && trim($item['title']) !== '') {
$extracted_title = trim($item['title']);
break;
}
}
}
if ($extracted_title) {
// Update track with the extracted title
$update_stmt = $pdo->prepare("UPDATE music_tracks SET title = ?, updated_at = NOW() WHERE id = ?");
if ($update_stmt->execute([$extracted_title, $missing_track['id']])) {
logMessage("✅ Fixed title for Track ID {$missing_track['id']}: $extracted_title");
echo "<p style='color: green;'>✅ Fixed title for Track ID {$missing_track['id']}: " . htmlspecialchars($extracted_title) . "</p>";
$title_fixed_count++;
}
}
}
}
logMessage("Title fixes complete: $title_fixed_count tracks updated");
}
echo "<h3>✅ Title Fixes: $title_fixed_count</h3>";
// Summary
$stmt = $pdo->prepare("
SELECT
COUNT(*) as total_tracks,
COUNT(CASE WHEN status = 'complete' THEN 1 END) as completed_tracks,
COUNT(CASE WHEN status = 'processing' THEN 1 END) as processing_tracks,
COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed_tracks,
COUNT(CASE WHEN status = 'complete' AND (title IS NULL OR title = '' OR title = 'Untitled Track') THEN 1 END) as missing_titles
FROM music_tracks
");
$stmt->execute();
$stats = $stmt->fetch();
echo "<h2>📊 Summary</h2>";
echo "<p>Total Tracks: {$stats['total_tracks']}</p>";
echo "<p>Completed: {$stats['completed_tracks']}</p>";
echo "<p>Processing: {$stats['processing_tracks']}</p>";
echo "<p>Failed: {$stats['failed_tracks']}</p>";
echo "<p>Still Missing Titles: {$stats['missing_titles']}</p>";
logMessage("Auto-fix completed. Stats: {$stats['total_tracks']} total, {$stats['completed_tracks']} complete, {$stats['processing_tracks']} processing, {$stats['failed_tracks']} failed, {$stats['missing_titles']} missing titles, $title_fixed_count titles fixed this run");
echo "<h2>🎯 Automation Setup</h2>";
echo "<p>To run this automatically, add to crontab:</p>";
echo "<pre># Check for stuck tracks every 15 minutes
*/15 * * * * /usr/bin/php /home/gositeme/domains/soundstudiopro.com/public_html/auto_fix_stuck_tracks.php > /dev/null 2>&1</pre>";
?>