diff --git a/app/Events/S3RestoreJobFinished.php b/app/Events/S3RestoreJobFinished.php index b1ce89c45..a672f472f 100644 --- a/app/Events/S3RestoreJobFinished.php +++ b/app/Events/S3RestoreJobFinished.php @@ -20,26 +20,22 @@ public function __construct($data) $container = data_get($data, 'container'); $serverId = data_get($data, 'serverId'); - // Clean up helper container and temporary files + // Most cleanup now happens inline during restore process + // This acts as a safety net for edge cases (errors, interruptions) if (filled($serverId)) { $commands = []; - // Stop and remove helper container + // Ensure helper container is removed (may already be gone from inline cleanup) if (filled($containerName)) { $commands[] = "docker rm -f {$containerName} 2>/dev/null || true"; } - // Clean up downloaded file from server /tmp + // Clean up server temp file if still exists (should already be cleaned) if (isSafeTmpPath($serverTmpPath)) { $commands[] = "rm -f {$serverTmpPath} 2>/dev/null || true"; } - // Clean up script from server - if (isSafeTmpPath($scriptPath)) { - $commands[] = "rm -f {$scriptPath} 2>/dev/null || true"; - } - - // Clean up files from database container + // Clean up any remaining files in database container (may already be cleaned) if (filled($container)) { if (isSafeTmpPath($containerTmpPath)) { $commands[] = "docker exec {$container} rm -f {$containerTmpPath} 2>/dev/null || true"; @@ -49,9 +45,11 @@ public function __construct($data) } } - $server = Server::find($serverId); - if ($server) { - instant_remote_process($commands, $server, throwError: false); + if (! empty($commands)) { + $server = Server::find($serverId); + if ($server) { + instant_remote_process($commands, $server, throwError: false); + } } } } diff --git a/app/Livewire/Project/Database/Import.php b/app/Livewire/Project/Database/Import.php index 216d4d5c9..b13c990f6 100644 --- a/app/Livewire/Project/Database/Import.php +++ b/app/Livewire/Project/Database/Import.php @@ -379,8 +379,10 @@ public function restoreFromS3() // Prepare all commands in sequence $commands = []; - // 1. Clean up any existing helper container + // 1. Clean up any existing helper container and temp files from previous runs $commands[] = "docker rm -f {$containerName} 2>/dev/null || true"; + $commands[] = "rm -f {$serverTmpPath} 2>/dev/null || true"; + $commands[] = "docker exec {$this->container} rm -f {$containerTmpPath} {$scriptPath} 2>/dev/null || true"; // 2. Start helper container on the database network $commands[] = "docker run -d --network {$destinationNetwork} --name {$containerName} {$fullImageName} sleep 3600"; @@ -394,15 +396,17 @@ public function restoreFromS3() // 4. Check file exists in S3 $commands[] = "docker exec {$containerName} mc stat s3temp/{$bucket}/{$cleanPath}"; - // 5. Download from S3 to helper container's internal /tmp + // 5. Download from S3 to helper container (progress shown by default) $commands[] = "docker exec {$containerName} mc cp s3temp/{$bucket}/{$cleanPath} {$helperTmpPath}"; - // 6. Copy file from helper container to server + // 6. Copy from helper to server, then immediately to database container $commands[] = "docker cp {$containerName}:{$helperTmpPath} {$serverTmpPath}"; - - // 7. Copy file from server to database container $commands[] = "docker cp {$serverTmpPath} {$this->container}:{$containerTmpPath}"; + // 7. Cleanup helper container and server temp file immediately (no longer needed) + $commands[] = "docker rm -f {$containerName} 2>/dev/null || true"; + $commands[] = "rm -f {$serverTmpPath} 2>/dev/null || true"; + // 8. Build and execute restore command inside database container $restoreCommand = $this->buildRestoreCommand($containerTmpPath); @@ -410,10 +414,12 @@ public function restoreFromS3() $commands[] = "echo \"{$restoreCommandBase64}\" | base64 -d > {$scriptPath}"; $commands[] = "chmod +x {$scriptPath}"; $commands[] = "docker cp {$scriptPath} {$this->container}:{$scriptPath}"; - $commands[] = "docker exec {$this->container} sh -c '{$scriptPath}'"; + + // 9. Execute restore and cleanup temp files immediately after completion + $commands[] = "docker exec {$this->container} sh -c '{$scriptPath} && rm -f {$containerTmpPath} {$scriptPath}'"; $commands[] = "docker exec {$this->container} sh -c 'echo \"Import finished with exit code $?\"'"; - // Execute all commands with cleanup event + // Execute all commands with cleanup event (as safety net for edge cases) $activity = remote_process($commands, $this->server, ignore_errors: true, callEventOnFinish: 'S3RestoreJobFinished', callEventData: [ 'containerName' => $containerName, 'serverTmpPath' => $serverTmpPath, @@ -426,7 +432,7 @@ public function restoreFromS3() // Dispatch activity to the monitor and open slide-over $this->dispatch('activityMonitor', $activity->id); $this->dispatch('databaserestore'); - $this->dispatch('info', 'Restoring database from S3. This may take a few minutes for large backups...'); + $this->dispatch('info', 'Restoring database from S3. Progress will be shown in the activity monitor...'); } catch (\Throwable $e) { $this->importRunning = false;