diff --git a/app/Actions/Docker/GetContainersStatus.php b/app/Actions/Docker/GetContainersStatus.php index 6c1a53f3a..95c22efc1 100644 --- a/app/Actions/Docker/GetContainersStatus.php +++ b/app/Actions/Docker/GetContainersStatus.php @@ -30,7 +30,7 @@ class GetContainersStatus $this->containerReplicates = $containerReplicates; $this->server = $server; if (! $this->server->isFunctional()) { - return 'Server is not ready.'; + return 'Server is not functional.'; } $this->applications = $this->server->applications(); $skip_these_applications = collect([]); diff --git a/app/Actions/Server/ResourcesCheck.php b/app/Actions/Server/ResourcesCheck.php new file mode 100644 index 000000000..e6b90ba38 --- /dev/null +++ b/app/Actions/Server/ResourcesCheck.php @@ -0,0 +1,41 @@ +subSeconds($seconds))->update(['status' => 'exited']); + ServiceApplication::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + ServiceDatabase::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandalonePostgresql::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneRedis::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneMongodb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneMysql::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneMariadb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneKeydb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneDragonfly::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + StandaloneClickhouse::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); + } catch (\Throwable $e) { + return handleError($e); + } + } +} diff --git a/app/Actions/Server/ServerCheck.php b/app/Actions/Server/ServerCheck.php new file mode 100644 index 000000000..51f6511c8 --- /dev/null +++ b/app/Actions/Server/ServerCheck.php @@ -0,0 +1,269 @@ +server = $server; + try { + if ($this->server->isFunctional() === false) { + return 'Server is not functional.'; + } + + if (! $this->server->isSwarmWorker() && ! $this->server->isBuildServer()) { + + if (isset($data)) { + $data = collect($data); + + $this->server->sentinelHeartbeat(); + + $this->containers = collect(data_get($data, 'containers')); + + $filesystemUsageRoot = data_get($data, 'filesystem_usage_root.used_percentage'); + ServerStorageCheckJob::dispatch($this->server, $filesystemUsageRoot); + + $containerReplicates = null; + $this->isSentinel = true; + + } else { + ['containers' => $this->containers, 'containerReplicates' => $containerReplicates] = $this->server->getContainers(); + ServerStorageCheckJob::dispatch($this->server); + } + + if (is_null($this->containers)) { + return 'No containers found.'; + } + + if (isset($containerReplicates)) { + foreach ($containerReplicates as $containerReplica) { + $name = data_get($containerReplica, 'Name'); + $this->containers = $this->containers->map(function ($container) use ($name, $containerReplica) { + if (data_get($container, 'Spec.Name') === $name) { + $replicas = data_get($containerReplica, 'Replicas'); + $running = str($replicas)->explode('/')[0]; + $total = str($replicas)->explode('/')[1]; + if ($running === $total) { + data_set($container, 'State.Status', 'running'); + data_set($container, 'State.Health.Status', 'healthy'); + } else { + data_set($container, 'State.Status', 'starting'); + data_set($container, 'State.Health.Status', 'unhealthy'); + } + } + + return $container; + }); + } + } + $this->checkContainers(); + + if ($this->server->isSentinelEnabled() && $this->isSentinel === false) { + CheckAndStartSentinelJob::dispatch($this->server); + } + + if ($this->server->isLogDrainEnabled()) { + $this->checkLogDrainContainer(); + } + + if ($this->server->proxySet() && ! $this->server->proxy->force_stop) { + $foundProxyContainer = $this->containers->filter(function ($value, $key) { + if ($this->server->isSwarm()) { + return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik'; + } else { + return data_get($value, 'Name') === '/coolify-proxy'; + } + })->first(); + if (! $foundProxyContainer) { + try { + $shouldStart = CheckProxy::run($this->server); + if ($shouldStart) { + StartProxy::run($this->server, false); + $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); + } + } catch (\Throwable $e) { + } + } else { + $this->server->proxy->status = data_get($foundProxyContainer, 'State.Status'); + $this->server->save(); + $connectProxyToDockerNetworks = connectProxyToNetworks($this->server); + instant_remote_process($connectProxyToDockerNetworks, $this->server, false); + } + } + } + } catch (\Throwable $e) { + return handleError($e); + } + } + + private function checkLogDrainContainer() + { + $foundLogDrainContainer = $this->containers->filter(function ($value, $key) { + return data_get($value, 'Name') === '/coolify-log-drain'; + })->first(); + if ($foundLogDrainContainer) { + $status = data_get($foundLogDrainContainer, 'State.Status'); + if ($status !== 'running') { + StartLogDrain::dispatch($this->server); + } + } else { + StartLogDrain::dispatch($this->server); + } + } + + private function checkContainers() + { + foreach ($this->containers as $container) { + if ($this->isSentinel) { + $labels = Arr::undot(data_get($container, 'labels')); + } else { + if ($this->server->isSwarm()) { + $labels = Arr::undot(data_get($container, 'Spec.Labels')); + } else { + $labels = Arr::undot(data_get($container, 'Config.Labels')); + } + + } + $managed = data_get($labels, 'coolify.managed'); + if (! $managed) { + continue; + } + $uuid = data_get($labels, 'coolify.name'); + if (! $uuid) { + $uuid = data_get($labels, 'com.docker.compose.service'); + } + + if ($this->isSentinel) { + $containerStatus = data_get($container, 'state'); + $containerHealth = data_get($container, 'health_status'); + } else { + $containerStatus = data_get($container, 'State.Status'); + $containerHealth = data_get($container, 'State.Health.Status', 'unhealthy'); + } + $containerStatus = "$containerStatus ($containerHealth)"; + + $applicationId = data_get($labels, 'coolify.applicationId'); + $serviceId = data_get($labels, 'coolify.serviceId'); + $databaseId = data_get($labels, 'coolify.databaseId'); + $pullRequestId = data_get($labels, 'coolify.pullRequestId'); + + if ($applicationId) { + // Application + if ($pullRequestId != 0) { + if (str($applicationId)->contains('-')) { + $applicationId = str($applicationId)->before('-'); + } + $preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first(); + if ($preview) { + $preview->update(['status' => $containerStatus]); + } + } else { + $application = Application::where('id', $applicationId)->first(); + if ($application) { + $application->update([ + 'status' => $containerStatus, + 'last_online_at' => now(), + ]); + } + } + } elseif (isset($serviceId)) { + // Service + $subType = data_get($labels, 'coolify.service.subType'); + $subId = data_get($labels, 'coolify.service.subId'); + $service = Service::where('id', $serviceId)->first(); + if (! $service) { + continue; + } + if ($subType === 'application') { + $service = ServiceApplication::where('id', $subId)->first(); + } else { + $service = ServiceDatabase::where('id', $subId)->first(); + } + if ($service) { + $service->update([ + 'status' => $containerStatus, + 'last_online_at' => now(), + ]); + if ($subType === 'database') { + $isPublic = data_get($service, 'is_public'); + if ($isPublic) { + $foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) { + if ($this->isSentinel) { + return data_get($value, 'name') === $uuid.'-proxy'; + } else { + + if ($this->server->isSwarm()) { + return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid"; + } else { + return data_get($value, 'Name') === "/$uuid-proxy"; + } + } + })->first(); + if (! $foundTcpProxy) { + StartDatabaseProxy::run($service); + } + } + } + } + } else { + // Database + if (is_null($this->databases)) { + $this->databases = $this->server->databases(); + } + $database = $this->databases->where('uuid', $uuid)->first(); + if ($database) { + $database->update([ + 'status' => $containerStatus, + 'last_online_at' => now(), + ]); + + $isPublic = data_get($database, 'is_public'); + if ($isPublic) { + $foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) { + if ($this->isSentinel) { + return data_get($value, 'name') === $uuid.'-proxy'; + } else { + if ($this->server->isSwarm()) { + return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid"; + } else { + + return data_get($value, 'Name') === "/$uuid-proxy"; + } + } + })->first(); + if (! $foundTcpProxy) { + StartDatabaseProxy::run($database); + $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server)); + } + } + } + } + } + } +} diff --git a/app/Console/Commands/Weird.php b/app/Console/Commands/Weird.php new file mode 100644 index 000000000..e471a5f96 --- /dev/null +++ b/app/Console/Commands/Weird.php @@ -0,0 +1,58 @@ +error('This command can only be run in development mode'); + + return; + } + $run = $this->option('run'); + if ($run) { + $servers = Server::all(); + foreach ($servers as $server) { + ServerCheck::dispatch($server); + } + + return; + } + $number = $this->option('number'); + for ($i = 0; $i < $number; $i++) { + $uuid = Str::uuid(); + $server = Server::create([ + 'name' => 'localhost-'.$uuid, + 'description' => 'This is a test docker container in development mode', + 'ip' => 'coolify-testing-host', + 'team_id' => 0, + 'private_key_id' => 1, + 'proxy' => [ + 'type' => ProxyTypes::NONE->value, + 'status' => ProxyStatus::EXITED->value, + ], + ]); + $server->settings->update([ + 'is_usable' => true, + 'is_reachable' => true, + ]); + } + } catch (\Exception $e) { + $this->error($e->getMessage()); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 7533e8932..9d1a2e40f 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,7 @@ namespace App\Console; +use App\Actions\Server\ResourcesCheck; use App\Jobs\CheckAndStartSentinelJob; use App\Jobs\CheckForUpdatesJob; use App\Jobs\CheckHelperImageJob; @@ -41,13 +42,16 @@ class Kernel extends ConsoleKernel // Instance Jobs $schedule->command('horizon:snapshot')->everyMinute(); $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer(); + $schedule->job(new CheckHelperImageJob)->everyFiveMinutes()->onOneServer(); + // Server Jobs - $this->checkScheduledBackups($schedule); $this->checkResources($schedule); + + $this->checkScheduledBackups($schedule); $this->checkScheduledTasks($schedule); + $schedule->command('uploads:clear')->everyTwoMinutes(); - $schedule->job(new CheckHelperImageJob)->everyFiveMinutes()->onOneServer(); } else { // Instance Jobs $schedule->command('horizon:snapshot')->everyFiveMinutes(); @@ -57,9 +61,11 @@ class Kernel extends ConsoleKernel $this->scheduleUpdates($schedule); // Server Jobs - $this->checkScheduledBackups($schedule); $this->checkResources($schedule); + $this->pullImages($schedule); + + $this->checkScheduledBackups($schedule); $this->checkScheduledTasks($schedule); $schedule->command('cleanup:database --yes')->daily(); @@ -109,12 +115,17 @@ class Kernel extends ConsoleKernel } else { $servers = $this->allServers; } + // $schedule->job(new ResourcesCheck)->everyMinute()->onOneServer(); + foreach ($servers as $server) { - $lastSentinelUpdate = $server->sentinel_updated_at; $serverTimezone = $server->settings->server_timezone; + + // Sentinel check + $lastSentinelUpdate = $server->sentinel_updated_at; if (Carbon::parse($lastSentinelUpdate)->isBefore(now()->subSeconds($server->waitBeforeDoingSshCheck()))) { $schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer(); } + if ($server->settings->force_docker_cleanup) { $schedule->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->timezone($serverTimezone)->onOneServer(); } else { diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index c80b4a7db..a0fdd0e97 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -230,7 +230,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $this->application_deployment_queue->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, ]); - if (! $this->server->isFunctional()) { + if ($this->server->isFunctional() === false) { $this->application_deployment_queue->addLogEntry('Server is not functional.'); $this->fail('Server is not functional.'); diff --git a/app/Jobs/ServerCheckNewJob.php b/app/Jobs/ServerCheckNewJob.php new file mode 100644 index 000000000..8455c9617 --- /dev/null +++ b/app/Jobs/ServerCheckNewJob.php @@ -0,0 +1,32 @@ +server); + } catch (\Throwable $e) { + return handleError($e); + } + } +} diff --git a/app/Jobs/ServerStorageCheckJob.php b/app/Jobs/ServerStorageCheckJob.php index cc838c77f..0723ffcee 100644 --- a/app/Jobs/ServerStorageCheckJob.php +++ b/app/Jobs/ServerStorageCheckJob.php @@ -30,8 +30,8 @@ class ServerStorageCheckJob implements ShouldBeEncrypted, ShouldQueue public function handle() { try { - if (! $this->server->isFunctional()) { - return 'Server is not ready.'; + if ($this->server->isFunctional() === false) { + return 'Server is not functional.'; } $team = data_get($this->server, 'team'); $serverDiskUsageNotificationThreshold = data_get($this->server, 'settings.server_disk_usage_notification_threshold'); diff --git a/app/Models/Application.php b/app/Models/Application.php index cd7bb533e..91abf2e3a 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -117,14 +117,31 @@ class Application extends BaseModel if ($application->fqdn === '') { $application->fqdn = null; } - $application->forceFill([ - 'fqdn' => $application->fqdn, - 'install_command' => str($application->install_command)->trim(), - 'build_command' => str($application->build_command)->trim(), - 'start_command' => str($application->start_command)->trim(), - 'base_directory' => str($application->base_directory)->trim(), - 'publish_directory' => str($application->publish_directory)->trim(), - ]); + $payload = []; + if ($application->isDirty('fqdn')) { + $payload['fqdn'] = $application->fqdn; + } + if ($application->isDirty('install_command')) { + $payload['install_command'] = str($application->install_command)->trim(); + } + if ($application->isDirty('build_command')) { + $payload['build_command'] = str($application->build_command)->trim(); + } + if ($application->isDirty('start_command')) { + $payload['start_command'] = str($application->start_command)->trim(); + } + if ($application->isDirty('base_directory')) { + $payload['base_directory'] = str($application->base_directory)->trim(); + } + if ($application->isDirty('publish_directory')) { + $payload['publish_directory'] = str($application->publish_directory)->trim(); + } + if ($application->isDirty('status')) { + $payload['last_online_at'] = now(); + } + if (count($payload) > 0) { + $application->forceFill($payload); + } }); static::created(function ($application) { ApplicationSetting::create([ diff --git a/app/Models/ApplicationPreview.php b/app/Models/ApplicationPreview.php index 04a0ab27e..bf2bf05bf 100644 --- a/app/Models/ApplicationPreview.php +++ b/app/Models/ApplicationPreview.php @@ -28,6 +28,11 @@ class ApplicationPreview extends BaseModel }); } }); + static::saving(function ($preview) { + if ($preview->isDirty('status')) { + $preview->forceFill(['last_online_at' => now()]); + } + }); } public static function findPreviewByApplicationAndPullId(int $application_id, int $pull_request_id) diff --git a/app/Models/Server.php b/app/Models/Server.php index 87800bbe9..1c6651017 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -507,20 +507,6 @@ $schema://$host { return Server::whereTeamId($teamId)->whereRelation('settings', 'is_reachable', true)->whereRelation('settings', 'is_build_server', true); } - public function skipServer() - { - if ($this->ip === '1.2.3.4') { - // ray('skipping 1.2.3.4'); - return true; - } - if ($this->settings->force_disabled === true) { - // ray('force_disabled'); - return true; - } - - return false; - } - public function isForceDisabled() { return $this->settings->force_disabled; @@ -691,7 +677,7 @@ $schema://$host { } } } else { - $containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this, false); + $containers = instant_remote_process(["docker container inspect $(docker container ls -aq) --format '{{json .}}'"], $this, false); $containers = format_docker_command_output_to_json($containers); $containerReplicates = collect([]); } @@ -919,9 +905,9 @@ $schema://$host { public function isFunctional() { - $isFunctional = $this->settings->is_reachable && $this->settings->is_usable && ! $this->settings->force_disabled; + $isFunctional = $this->settings->is_reachable && $this->settings->is_usable && $this->settings->force_disabled === false && $this->ip !== '1.2.3.4'; - if (! $isFunctional) { + if ($isFunctional === false) { Storage::disk('ssh-mux')->delete($this->muxFilename()); } @@ -988,7 +974,7 @@ $schema://$host { public function status(): bool { - if ($this->skipServer()) { + if ($this->isFunctional() === false) { return false; } ['uptime' => $uptime] = $this->validateConnection(false); @@ -1058,7 +1044,7 @@ $schema://$host { { config()->set('constants.ssh.mux_enabled', ! $isManualCheck); - if ($this->skipServer()) { + if ($this->isFunctional() === false) { return ['uptime' => false, 'error' => 'Server skipped.']; } try { diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index 0e79e1e2e..305913068 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -19,6 +19,11 @@ class ServiceApplication extends BaseModel $service->persistentStorages()->delete(); $service->fileStorages()->delete(); }); + static::saving(function ($service) { + if ($service->isDirty('status')) { + $service->forceFill(['last_online_at' => now()]); + } + }); } public function restart() diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index 927527118..6641509dd 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -17,6 +17,11 @@ class ServiceDatabase extends BaseModel $service->persistentStorages()->delete(); $service->fileStorages()->delete(); }); + static::saving(function ($service) { + if ($service->isDirty('status')) { + $service->forceFill(['last_online_at' => now()]); + } + }); } public function restart() diff --git a/app/Models/StandaloneClickhouse.php b/app/Models/StandaloneClickhouse.php index fa27d50d8..6d66c6854 100644 --- a/app/Models/StandaloneClickhouse.php +++ b/app/Models/StandaloneClickhouse.php @@ -38,6 +38,11 @@ class StandaloneClickhouse extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/app/Models/StandaloneDragonfly.php b/app/Models/StandaloneDragonfly.php index fa0bd4b44..f7d83f0a3 100644 --- a/app/Models/StandaloneDragonfly.php +++ b/app/Models/StandaloneDragonfly.php @@ -38,6 +38,11 @@ class StandaloneDragonfly extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/app/Models/StandaloneKeydb.php b/app/Models/StandaloneKeydb.php index 56ee4d4a2..083c743d9 100644 --- a/app/Models/StandaloneKeydb.php +++ b/app/Models/StandaloneKeydb.php @@ -38,6 +38,11 @@ class StandaloneKeydb extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php index c55a76af7..833dad6c4 100644 --- a/app/Models/StandaloneMariadb.php +++ b/app/Models/StandaloneMariadb.php @@ -38,6 +38,11 @@ class StandaloneMariadb extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php index 3f12a8557..dd8893180 100644 --- a/app/Models/StandaloneMongodb.php +++ b/app/Models/StandaloneMongodb.php @@ -42,6 +42,11 @@ class StandaloneMongodb extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php index 0d8359f88..710fea1bc 100644 --- a/app/Models/StandaloneMysql.php +++ b/app/Models/StandaloneMysql.php @@ -39,6 +39,11 @@ class StandaloneMysql extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index f31582c35..4a457a6cf 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -39,6 +39,11 @@ class StandalonePostgresql extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } public function workdir() diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index 119978530..826bb951c 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -34,6 +34,11 @@ class StandaloneRedis extends BaseModel $database->environment_variables()->delete(); $database->tags()->detach(); }); + static::saving(function ($database) { + if ($database->isDirty('status')) { + $database->forceFill(['last_online_at' => now()]); + } + }); } protected function serverStatus(): Attribute diff --git a/database/migrations/2024_11_02_213214_add_last_online_at_to_resources.php b/database/migrations/2024_11_02_213214_add_last_online_at_to_resources.php new file mode 100644 index 000000000..51b8fb3ba --- /dev/null +++ b/database/migrations/2024_11_02_213214_add_last_online_at_to_resources.php @@ -0,0 +1,96 @@ +timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('application_previews', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('service_applications', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('service_databases', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_postgresqls', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_redis', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_mongodbs', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_mysqls', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_mariadbs', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_keydbs', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_dragonflies', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + Schema::table('standalone_clickhouses', function (Blueprint $table) { + $table->timestamp('last_online_at')->default(now())->after('updated_at'); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('applications', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('application_previews', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('service_applications', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('service_databases', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_postgresqls', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_redis', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_mongodbs', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_mysqls', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_mariadbs', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_keydbs', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_dragonflies', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + Schema::table('standalone_clickhouses', function (Blueprint $table) { + $table->dropColumn('last_online_at'); + }); + + } +}; diff --git a/routes/api.php b/routes/api.php index 572325810..1942d3312 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,6 +14,7 @@ use App\Http\Middleware\ApiAllowed; use App\Http\Middleware\IgnoreReadOnlyApiToken; use App\Http\Middleware\OnlyRootApiToken; use App\Jobs\PushServerUpdateJob; +use App\Jobs\ServerCheckNewJob; use App\Models\Server; use Illuminate\Support\Facades\Route; @@ -151,6 +152,7 @@ Route::group([ } $data = request()->all(); + // ServerCheckNewJob::dispatch($server, $data); PushServerUpdateJob::dispatch($server, $data); return response()->json(['message' => 'ok'], 200);