diff --git a/app/Actions/Database/StopDatabase.php b/app/Actions/Database/StopDatabase.php index d562ec56f..29ce794cf 100644 --- a/app/Actions/Database/StopDatabase.php +++ b/app/Actions/Database/StopDatabase.php @@ -10,25 +10,65 @@ use App\Models\StandaloneMongodb; use App\Models\StandaloneMysql; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; +use Illuminate\Support\Facades\Process; use Lorisleiva\Actions\Concerns\AsAction; +use App\Actions\Server\CleanupDocker; class StopDatabase { use AsAction; - public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database) + public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database, bool $isDeleteOperation = false) { $server = $database->destination->server; - if (! $server->isFunctional()) { + if (!$server->isFunctional()) { return 'Server is not functional'; } - instant_remote_process(command: ["docker stop --time=30 $database->uuid"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm $database->uuid"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm -f $database->uuid"], server: $server, throwError: false); + $this->stopContainer($database, $database->uuid, 300); + if (!$isDeleteOperation) { + $this->deleteConnectedNetworks($database->uuid, $server); //Probably not needed as DBs do not have a network normally + CleanupDocker::run($server, true); + } if ($database->is_public) { StopDatabaseProxy::run($database); } + + return 'Database stopped successfully'; + } + + private function stopContainer($database, string $containerName, int $timeout = 300): void + { + $server = $database->destination->server; + + $process = Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); + + $startTime = time(); + while ($process->running()) { + if (time() - $startTime >= $timeout) { + $this->forceStopContainer($containerName, $server); + break; + } + usleep(100000); + } + + $this->removeContainer($containerName, $server); + } + + private function forceStopContainer(string $containerName, $server): void + { + instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); + } + + private function removeContainer(string $containerName, $server): void + { + instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); + } + + private function deleteConnectedNetworks($uuid, $server) + { + instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); + instant_remote_process(["docker network rm {$uuid}"], $server, false); } } diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 85c61dc83..6b348f830 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -31,4 +31,4 @@ class StopService return $e->getMessage(); } } -} \ No newline at end of file +} diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index 6e102266a..1f4e835e9 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -56,17 +56,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue case 'standalone-dragonfly': case 'standalone-clickhouse': $persistentStorages = $this->resource?->persistentStorages()?->get(); - StopDatabase::run($this->resource); - // TODO - // DBs do not have a network normally? - //if ($this->deleteConnectedNetworks) { - // $this->resource?->delete_connected_networks($this->resource->uuid); - // } - // } - // $server = data_get($this->resource, 'server'); - // if ($this->deleteImages && $server) { - // CleanupDocker::run($server, true); - // } + StopDatabase::run($this->resource, true); break; case 'service': StopService::run($this->resource, true); @@ -80,10 +70,10 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue if ($this->deleteConfigurations) { $this->resource?->delete_configurations(); } - + $server = data_get($this->resource, 'server'); if ($this->deleteImages && $server) { - CleanupDocker::run($server, true); + CleanupDocker::run($server, true); //this is run for DBs but it does not work for DBs } if ($this->deleteConnectedNetworks) {