diff --git a/app/Actions/Database/StartClickhouse.php b/app/Actions/Database/StartClickhouse.php index 1128b8f8f..525e736c3 100644 --- a/app/Actions/Database/StartClickhouse.php +++ b/app/Actions/Database/StartClickhouse.php @@ -50,13 +50,9 @@ public function handle(StandaloneClickhouse $database) ], ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => ['CMD', 'clickhouse-client', '--user', (string) $this->database->clickhouse_admin_user, '--password', (string) $this->database->clickhouse_admin_password, '--query', 'SELECT 1'], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', 'clickhouse-client', '--user', (string) $this->database->clickhouse_admin_user, '--password', (string) $this->database->clickhouse_admin_password, '--query', 'SELECT 1', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartDragonfly.php b/app/Actions/Database/StartDragonfly.php index 530ba7d23..b78a0987d 100644 --- a/app/Actions/Database/StartDragonfly.php +++ b/app/Actions/Database/StartDragonfly.php @@ -106,13 +106,9 @@ public function handle(StandaloneDragonfly $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => ['CMD', 'redis-cli', '-a', (string) $this->database->dragonfly_password, 'ping'], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', 'redis-cli', '-a', (string) $this->database->dragonfly_password, 'ping', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartKeydb.php b/app/Actions/Database/StartKeydb.php index e9acd0b3c..89258fe24 100644 --- a/app/Actions/Database/StartKeydb.php +++ b/app/Actions/Database/StartKeydb.php @@ -108,13 +108,9 @@ public function handle(StandaloneKeydb $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => ['CMD', 'keydb-cli', '--pass', (string) $this->database->keydb_password, 'ping'], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', 'keydb-cli', '--pass', (string) $this->database->keydb_password, 'ping', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartMariadb.php b/app/Actions/Database/StartMariadb.php index 17ed2a9a8..2e8faea9a 100644 --- a/app/Actions/Database/StartMariadb.php +++ b/app/Actions/Database/StartMariadb.php @@ -103,13 +103,9 @@ public function handle(StandaloneMariadb $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => ['CMD', 'healthcheck.sh', '--connect', '--innodb_initialized'], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', 'healthcheck.sh', '--connect', '--innodb_initialized', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php index e5973e807..80ec812a1 100644 --- a/app/Actions/Database/StartMongodb.php +++ b/app/Actions/Database/StartMongodb.php @@ -109,17 +109,11 @@ public function handle(StandaloneMongodb $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => [ - 'CMD', - 'echo', - 'ok', - ], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', + 'echo', + 'ok', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartMysql.php b/app/Actions/Database/StartMysql.php index f9d75e0c8..0445bddcd 100644 --- a/app/Actions/Database/StartMysql.php +++ b/app/Actions/Database/StartMysql.php @@ -103,13 +103,9 @@ public function handle(StandaloneMysql $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => ['CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', "-p{$this->database->mysql_root_password}"], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', "-p{$this->database->mysql_root_password}", + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php index 520cbdec4..ae7ae9860 100644 --- a/app/Actions/Database/StartPostgresql.php +++ b/app/Actions/Database/StartPostgresql.php @@ -110,13 +110,9 @@ public function handle(StandalonePostgresql $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => ['CMD', 'psql', '-U', (string) $this->database->postgres_user, '-d', (string) $this->database->postgres_db, '-c', 'SELECT 1'], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD', 'psql', '-U', (string) $this->database->postgres_user, '-d', (string) $this->database->postgres_db, '-c', 'SELECT 1', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index e4bfd98e1..64b434821 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -105,17 +105,11 @@ public function handle(StandaloneRedis $database) $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), - 'healthcheck' => [ - 'test' => [ - 'CMD-SHELL', - 'redis-cli', - 'ping', - ], - 'interval' => "{$this->database->health_check_interval}s", - 'timeout' => "{$this->database->health_check_timeout}s", - 'retries' => $this->database->health_check_retries, - 'start_period' => "{$this->database->health_check_start_period}s", - ], + 'healthcheck' => $this->database->healthCheckConfiguration([ + 'CMD-SHELL', + 'redis-cli', + 'ping', + ]), 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, diff --git a/app/Http/Controllers/Api/DatabasesController.php b/app/Http/Controllers/Api/DatabasesController.php index e2d2aad92..bceef4d39 100644 --- a/app/Http/Controllers/Api/DatabasesController.php +++ b/app/Http/Controllers/Api/DatabasesController.php @@ -299,11 +299,11 @@ public function database_by_uuid(Request $request) 'mysql_user' => ['type' => 'string', 'description' => 'MySQL user'], 'mysql_database' => ['type' => 'string', 'description' => 'MySQL database'], 'mysql_conf' => ['type' => 'string', 'description' => 'MySQL conf'], - 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Enable the database healthcheck probe.'], - 'health_check_interval' => ['type' => 'integer', 'description' => 'Healthcheck interval in seconds.'], - 'health_check_timeout' => ['type' => 'integer', 'description' => 'Healthcheck timeout in seconds.'], - 'health_check_retries' => ['type' => 'integer', 'description' => 'Healthcheck retries count.'], - 'health_check_start_period' => ['type' => 'integer', 'description' => 'Healthcheck start period in seconds.'], + 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Enable the database healthcheck probe.', 'default' => true], + 'health_check_interval' => ['type' => 'integer', 'description' => 'Healthcheck interval in seconds.', 'minimum' => 1, 'default' => 15], + 'health_check_timeout' => ['type' => 'integer', 'description' => 'Healthcheck timeout in seconds.', 'minimum' => 1, 'default' => 5], + 'health_check_retries' => ['type' => 'integer', 'description' => 'Healthcheck retries count.', 'minimum' => 1, 'default' => 5], + 'health_check_start_period' => ['type' => 'integer', 'description' => 'Healthcheck start period in seconds.', 'minimum' => 0, 'default' => 5], ], ), ) diff --git a/app/Livewire/Project/Database/Health.php b/app/Livewire/Project/Database/Health.php index 33540d74e..535e73689 100644 --- a/app/Livewire/Project/Database/Health.php +++ b/app/Livewire/Project/Database/Health.php @@ -2,6 +2,7 @@ namespace App\Livewire\Project\Database; +use Illuminate\Contracts\View\View; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Attributes\Validate; use Livewire\Component; @@ -27,7 +28,7 @@ class Health extends Component #[Validate(['integer', 'min:0'])] public int $healthCheckStartPeriod = 5; - public function mount() + public function mount(): void { $this->authorize('view', $this->database); $this->syncData(); @@ -52,29 +53,64 @@ public function syncData(bool $toModel = false): void } } - public function instantSave() + public function instantSave(): void { $this->submit(); } - public function submit() + public function submit(): void { + $updateSuccessful = false; + try { $this->authorize('update', $this->database); $this->syncData(true); + $updateSuccessful = true; $this->dispatch('success', 'Health check updated. Restart the database to apply the changes.'); } catch (\Throwable $e) { - return handleError($e, $this); - } finally { - if (is_null($this->database->config_hash)) { - $this->database->isConfigurationChanged(true); - } else { - $this->dispatch('configurationChanged'); - } + handleError($e, $this); } + + if (! $updateSuccessful) { + return; + } + + $this->markConfigurationChanged(); } - public function render() + public function toggleHealthcheck(): void + { + $updateSuccessful = false; + + try { + $this->authorize('update', $this->database); + $this->healthCheckEnabled = ! $this->healthCheckEnabled; + $this->syncData(true); + $updateSuccessful = true; + $this->dispatch('success', 'Health check '.($this->healthCheckEnabled ? 'enabled' : 'disabled').'. Restart the database to apply the changes.'); + } catch (\Throwable $e) { + handleError($e, $this); + } + + if (! $updateSuccessful) { + return; + } + + $this->markConfigurationChanged(); + } + + private function markConfigurationChanged(): void + { + if (is_null($this->database->config_hash)) { + $this->database->isConfigurationChanged(true); + + return; + } + + $this->dispatch('configurationChanged'); + } + + public function render(): View { return view('livewire.project.database.health'); } diff --git a/app/Models/StandaloneClickhouse.php b/app/Models/StandaloneClickhouse.php index 1e68046f9..b104be642 100644 --- a/app/Models/StandaloneClickhouse.php +++ b/app/Models/StandaloneClickhouse.php @@ -122,7 +122,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandaloneDragonfly.php b/app/Models/StandaloneDragonfly.php index 5f76be884..2232ec772 100644 --- a/app/Models/StandaloneDragonfly.php +++ b/app/Models/StandaloneDragonfly.php @@ -121,7 +121,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandaloneKeydb.php b/app/Models/StandaloneKeydb.php index 6d3b5a82b..b9f9f765b 100644 --- a/app/Models/StandaloneKeydb.php +++ b/app/Models/StandaloneKeydb.php @@ -122,7 +122,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->keydb_conf; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php index 1058d8721..cd94b6c9b 100644 --- a/app/Models/StandaloneMariadb.php +++ b/app/Models/StandaloneMariadb.php @@ -125,7 +125,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->mariadb_conf; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php index 4657f1d5e..7d2ffbd74 100644 --- a/app/Models/StandaloneMongodb.php +++ b/app/Models/StandaloneMongodb.php @@ -131,7 +131,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->mongo_conf; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php index f3d0ad55f..f752312d3 100644 --- a/app/Models/StandaloneMysql.php +++ b/app/Models/StandaloneMysql.php @@ -127,7 +127,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->mysql_conf; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index 39482892d..04d2291b3 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -169,7 +169,7 @@ public function deleteVolumes() public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->postgres_initdb_args.$this->postgres_host_auth_method; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index 3d1d11138..efb0254fb 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -126,7 +126,7 @@ protected function serverStatus(): Attribute public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->redis_conf; - $newConfigHash .= $this->health_check_enabled.$this->health_check_interval.$this->health_check_timeout.$this->health_check_retries.$this->health_check_start_period; + $newConfigHash .= $this->healthCheckConfigurationHash(); $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); diff --git a/app/Traits/HasDatabaseHealthCheck.php b/app/Traits/HasDatabaseHealthCheck.php index 2602ecb23..62ca345ed 100644 --- a/app/Traits/HasDatabaseHealthCheck.php +++ b/app/Traits/HasDatabaseHealthCheck.php @@ -31,4 +31,15 @@ public function healthCheckConfiguration(array $test): array 'start_period' => ($this->health_check_start_period ?? 5).'s', ]; } + + protected function healthCheckConfigurationHash(): string + { + return implode('|', [ + (int) ($this->health_check_enabled ?? true), + $this->health_check_interval ?? 15, + $this->health_check_timeout ?? 5, + $this->health_check_retries ?? 5, + $this->health_check_start_period ?? 5, + ]); + } } diff --git a/openapi.json b/openapi.json index d3d25bacc..f3bda9ab8 100644 --- a/openapi.json +++ b/openapi.json @@ -4608,23 +4608,32 @@ }, "health_check_enabled": { "type": "boolean", - "description": "Enable the database healthcheck probe." + "description": "Enable the database healthcheck probe.", + "default": true }, "health_check_interval": { "type": "integer", - "description": "Healthcheck interval in seconds." + "description": "Healthcheck interval in seconds.", + "minimum": 1, + "default": 15 }, "health_check_timeout": { "type": "integer", - "description": "Healthcheck timeout in seconds." + "description": "Healthcheck timeout in seconds.", + "minimum": 1, + "default": 5 }, "health_check_retries": { "type": "integer", - "description": "Healthcheck retries count." + "description": "Healthcheck retries count.", + "minimum": 1, + "default": 5 }, "health_check_start_period": { "type": "integer", - "description": "Healthcheck start period in seconds." + "description": "Healthcheck start period in seconds.", + "minimum": 0, + "default": 5 } }, "type": "object" diff --git a/openapi.yaml b/openapi.yaml index 469a0c38d..fae8d7110 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -2953,18 +2953,27 @@ paths: health_check_enabled: type: boolean description: 'Enable the database healthcheck probe.' + default: true health_check_interval: type: integer description: 'Healthcheck interval in seconds.' + minimum: 1 + default: 15 health_check_timeout: type: integer description: 'Healthcheck timeout in seconds.' + minimum: 1 + default: 5 health_check_retries: type: integer description: 'Healthcheck retries count.' + minimum: 1 + default: 5 health_check_start_period: type: integer description: 'Healthcheck start period in seconds.' + minimum: 0 + default: 5 type: object responses: '200': diff --git a/resources/views/livewire/project/database/configuration.blade.php b/resources/views/livewire/project/database/configuration.blade.php index d6aac7f30..6e2ac208b 100644 --- a/resources/views/livewire/project/database/configuration.blade.php +++ b/resources/views/livewire/project/database/configuration.blade.php @@ -15,14 +15,14 @@ href="{{ route('project.database.servers', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Servers Persistent Storage - Healthcheck @can('update', $database) Import Backup @endcan Webhooks + Healthcheck Resource Limits

Healthcheck

Save - -
Configure how Docker checks this database's health. A higher interval lowers - dockerd/containerd CPU and load on servers running many databases. Restart the - database to apply changes.
-
- - @if ($healthCheckEnabled) -
- - - - -
+ @if (!$healthCheckEnabled) + + + @else + Disable Healthcheck @endif
+
Define how your resource's health should be checked.
+
+ @if (!$healthCheckEnabled) + +

Docker runs no healthcheck probe for this database and Coolify can no longer report a healthy/unhealthy state.

+
+ @endif + +
+ + + + +
+
diff --git a/resources/views/livewire/project/shared/health-checks.blade.php b/resources/views/livewire/project/shared/health-checks.blade.php index 8662b0b50..ac2063c2e 100644 --- a/resources/views/livewire/project/shared/health-checks.blade.php +++ b/resources/views/livewire/project/shared/health-checks.blade.php @@ -1,6 +1,6 @@
-

Healthchecks

+

Healthcheck

Save @if (!$healthCheckEnabled) isHealthcheckEnabled())->toBeFalse(); }); + +it('uses distinct hash fragments for ambiguous healthcheck values', function () { + $enabledDatabase = new StandalonePostgresql([ + 'health_check_enabled' => true, + 'health_check_interval' => 5, + 'health_check_timeout' => 5, + 'health_check_retries' => 5, + 'health_check_start_period' => 5, + ]); + + $disabledDatabase = new StandalonePostgresql([ + 'health_check_enabled' => false, + 'health_check_interval' => 15, + 'health_check_timeout' => 5, + 'health_check_retries' => 5, + 'health_check_start_period' => 5, + ]); + + $getHashFragment = function () { + return $this->healthCheckConfigurationHash(); + }; + + expect($getHashFragment->call($enabledDatabase)) + ->toBe('1|5|5|5|5') + ->not->toBe($getHashFragment->call($disabledDatabase)) + ->and($getHashFragment->call($disabledDatabase))->toBe('0|15|5|5|5'); +}); + +it('does not mark configuration changed when health update authorization fails', function () { + $database = new class + { + public ?string $config_hash = null; + + public int $configurationChangedChecks = 0; + + public function isConfigurationChanged(bool $save = false): bool + { + $this->configurationChangedChecks++; + + return true; + } + }; + + $component = new class extends Health + { + public array $dispatchedEvents = []; + + public function authorize($ability, $arguments = []) + { + throw new AuthorizationException('This action is unauthorized.'); + } + + public function dispatch($event, ...$params) + { + $this->dispatchedEvents[] = $event; + + return null; + } + }; + + $component->database = $database; + $component->submit(); + + expect($database->configurationChangedChecks)->toBe(0) + ->and($component->dispatchedEvents)->toBe(['error']); +}); + +it('toggles database healthcheck and marks configuration changed', function () { + $database = new class + { + public ?string $config_hash = 'existing'; + + public bool $health_check_enabled = false; + + public int $health_check_interval = 15; + + public int $health_check_timeout = 5; + + public int $health_check_retries = 5; + + public int $health_check_start_period = 5; + + public int $saveCalls = 0; + + public function save(): void + { + $this->saveCalls++; + } + }; + + $component = new class extends Health + { + public array $dispatchedEvents = []; + + public function authorize($ability, $arguments = []) + { + return true; + } + + public function dispatch($event, ...$params) + { + $this->dispatchedEvents[] = $event; + + return null; + } + + public function syncData(bool $toModel = false): void + { + if ($toModel) { + $this->database->health_check_enabled = $this->healthCheckEnabled; + $this->database->save(); + } + } + }; + + $component->database = $database; + $component->healthCheckEnabled = false; + $component->healthCheckInterval = 15; + $component->healthCheckTimeout = 5; + $component->healthCheckRetries = 5; + $component->healthCheckStartPeriod = 5; + + $component->toggleHealthcheck(); + + expect($database->health_check_enabled)->toBeTrue() + ->and($database->saveCalls)->toBe(1) + ->and($component->dispatchedEvents)->toBe(['success', 'configurationChanged']); +});