mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
Fix container status display: preserve "Restarting" for applications and sub-resources
Add preserveRestarting parameter to ContainerStatusAggregator to allow applications and service sub-resources to display "Restarting" status instead of being marked as "Degraded". This gives better visibility into container restart behavior. - Update ContainerStatusAggregator to accept preserveRestarting parameter (defaults to false) - Update GetContainersStatus to use preserveRestarting: true for applications and service sub-resources - Update PushServerUpdateJob to use preserveRestarting: true for applications and service sub-resources - Add comprehensive documentation explaining the parameter behavior and when to use it 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -461,9 +461,10 @@ class GetContainersStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use ContainerStatusAggregator service for state machine logic
|
// Use ContainerStatusAggregator service for state machine logic
|
||||||
|
// Use preserveRestarting: true so applications show "Restarting" instead of "Degraded"
|
||||||
$aggregator = new ContainerStatusAggregator;
|
$aggregator = new ContainerStatusAggregator;
|
||||||
|
|
||||||
return $aggregator->aggregateFromStrings($relevantStatuses, $maxRestartCount);
|
return $aggregator->aggregateFromStrings($relevantStatuses, $maxRestartCount, preserveRestarting: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function aggregateServiceContainerStatuses($services)
|
private function aggregateServiceContainerStatuses($services)
|
||||||
@@ -518,8 +519,9 @@ class GetContainersStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use ContainerStatusAggregator service for state machine logic
|
// Use ContainerStatusAggregator service for state machine logic
|
||||||
|
// Use preserveRestarting: true so individual sub-resources show "Restarting" instead of "Degraded"
|
||||||
$aggregator = new ContainerStatusAggregator;
|
$aggregator = new ContainerStatusAggregator;
|
||||||
$aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses);
|
$aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, preserveRestarting: true);
|
||||||
|
|
||||||
// Update service sub-resource status with aggregated result
|
// Update service sub-resource status with aggregated result
|
||||||
if ($aggregatedStatus) {
|
if ($aggregatedStatus) {
|
||||||
|
|||||||
@@ -300,8 +300,9 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use ContainerStatusAggregator service for state machine logic
|
// Use ContainerStatusAggregator service for state machine logic
|
||||||
|
// Use preserveRestarting: true so applications show "Restarting" instead of "Degraded"
|
||||||
$aggregator = new ContainerStatusAggregator;
|
$aggregator = new ContainerStatusAggregator;
|
||||||
$aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, 0);
|
$aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, 0, preserveRestarting: true);
|
||||||
|
|
||||||
// Update application status with aggregated result
|
// Update application status with aggregated result
|
||||||
if ($aggregatedStatus && $application->status !== $aggregatedStatus) {
|
if ($aggregatedStatus && $application->status !== $aggregatedStatus) {
|
||||||
@@ -360,8 +361,9 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced
|
|||||||
|
|
||||||
// Use ContainerStatusAggregator service for state machine logic
|
// Use ContainerStatusAggregator service for state machine logic
|
||||||
// NOTE: Sentinel does NOT provide restart count data, so maxRestartCount is always 0
|
// NOTE: Sentinel does NOT provide restart count data, so maxRestartCount is always 0
|
||||||
|
// Use preserveRestarting: true so individual sub-resources show "Restarting" instead of "Degraded"
|
||||||
$aggregator = new ContainerStatusAggregator;
|
$aggregator = new ContainerStatusAggregator;
|
||||||
$aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, 0);
|
$aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, 0, preserveRestarting: true);
|
||||||
|
|
||||||
// Update service sub-resource status with aggregated result
|
// Update service sub-resource status with aggregated result
|
||||||
if ($aggregatedStatus && $subResource->status !== $aggregatedStatus) {
|
if ($aggregatedStatus && $subResource->status !== $aggregatedStatus) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*
|
*
|
||||||
* State Priority (highest to lowest):
|
* State Priority (highest to lowest):
|
||||||
* 1. Degraded (from sub-resources) → degraded:unhealthy
|
* 1. Degraded (from sub-resources) → degraded:unhealthy
|
||||||
* 2. Restarting → degraded:unhealthy
|
* 2. Restarting → degraded:unhealthy (or restarting:unknown if preserveRestarting=true)
|
||||||
* 3. Crash Loop (exited with restarts) → degraded:unhealthy
|
* 3. Crash Loop (exited with restarts) → degraded:unhealthy
|
||||||
* 4. Mixed (running + exited) → degraded:unhealthy
|
* 4. Mixed (running + exited) → degraded:unhealthy
|
||||||
* 5. Mixed (running + starting) → starting:unknown
|
* 5. Mixed (running + starting) → starting:unknown
|
||||||
@@ -26,6 +26,13 @@ use Illuminate\Support\Facades\Log;
|
|||||||
* 8. Paused → paused:unknown
|
* 8. Paused → paused:unknown
|
||||||
* 9. Starting/Created → starting:unknown
|
* 9. Starting/Created → starting:unknown
|
||||||
* 10. Exited → exited
|
* 10. Exited → exited
|
||||||
|
*
|
||||||
|
* The $preserveRestarting parameter controls whether "restarting" containers should be
|
||||||
|
* reported as "restarting:unknown" (true) or "degraded:unhealthy" (false, default).
|
||||||
|
* - Use preserveRestarting=true for individual sub-resources (ServiceApplication/ServiceDatabase)
|
||||||
|
* so they show "Restarting" in the UI.
|
||||||
|
* - Use preserveRestarting=false for overall Service status aggregation where any restarting
|
||||||
|
* container should mark the entire service as "Degraded".
|
||||||
*/
|
*/
|
||||||
class ContainerStatusAggregator
|
class ContainerStatusAggregator
|
||||||
{
|
{
|
||||||
@@ -34,9 +41,10 @@ class ContainerStatusAggregator
|
|||||||
*
|
*
|
||||||
* @param Collection $containerStatuses Collection of status strings (e.g., "running (healthy)", "running:healthy")
|
* @param Collection $containerStatuses Collection of status strings (e.g., "running (healthy)", "running:healthy")
|
||||||
* @param int $maxRestartCount Maximum restart count across containers (for crash loop detection)
|
* @param int $maxRestartCount Maximum restart count across containers (for crash loop detection)
|
||||||
|
* @param bool $preserveRestarting If true, "restarting" containers return "restarting:unknown" instead of "degraded:unhealthy"
|
||||||
* @return string Aggregated status in colon format (e.g., "running:healthy")
|
* @return string Aggregated status in colon format (e.g., "running:healthy")
|
||||||
*/
|
*/
|
||||||
public function aggregateFromStrings(Collection $containerStatuses, int $maxRestartCount = 0): string
|
public function aggregateFromStrings(Collection $containerStatuses, int $maxRestartCount = 0, bool $preserveRestarting = false): string
|
||||||
{
|
{
|
||||||
// Validate maxRestartCount parameter
|
// Validate maxRestartCount parameter
|
||||||
if ($maxRestartCount < 0) {
|
if ($maxRestartCount < 0) {
|
||||||
@@ -107,7 +115,8 @@ class ContainerStatusAggregator
|
|||||||
$hasPaused,
|
$hasPaused,
|
||||||
$hasDead,
|
$hasDead,
|
||||||
$hasDegraded,
|
$hasDegraded,
|
||||||
$maxRestartCount
|
$maxRestartCount,
|
||||||
|
$preserveRestarting
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +125,10 @@ class ContainerStatusAggregator
|
|||||||
*
|
*
|
||||||
* @param Collection $containers Collection of Docker container objects with State property
|
* @param Collection $containers Collection of Docker container objects with State property
|
||||||
* @param int $maxRestartCount Maximum restart count across containers (for crash loop detection)
|
* @param int $maxRestartCount Maximum restart count across containers (for crash loop detection)
|
||||||
|
* @param bool $preserveRestarting If true, "restarting" containers return "restarting:unknown" instead of "degraded:unhealthy"
|
||||||
* @return string Aggregated status in colon format (e.g., "running:healthy")
|
* @return string Aggregated status in colon format (e.g., "running:healthy")
|
||||||
*/
|
*/
|
||||||
public function aggregateFromContainers(Collection $containers, int $maxRestartCount = 0): string
|
public function aggregateFromContainers(Collection $containers, int $maxRestartCount = 0, bool $preserveRestarting = false): string
|
||||||
{
|
{
|
||||||
// Validate maxRestartCount parameter
|
// Validate maxRestartCount parameter
|
||||||
if ($maxRestartCount < 0) {
|
if ($maxRestartCount < 0) {
|
||||||
@@ -185,7 +195,8 @@ class ContainerStatusAggregator
|
|||||||
$hasPaused,
|
$hasPaused,
|
||||||
$hasDead,
|
$hasDead,
|
||||||
false, // $hasDegraded - not applicable for container objects, only for status strings
|
false, // $hasDegraded - not applicable for container objects, only for status strings
|
||||||
$maxRestartCount
|
$maxRestartCount,
|
||||||
|
$preserveRestarting
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +213,7 @@ class ContainerStatusAggregator
|
|||||||
* @param bool $hasDead Has at least one dead/removing container
|
* @param bool $hasDead Has at least one dead/removing container
|
||||||
* @param bool $hasDegraded Has at least one degraded container
|
* @param bool $hasDegraded Has at least one degraded container
|
||||||
* @param int $maxRestartCount Maximum restart count (for crash loop detection)
|
* @param int $maxRestartCount Maximum restart count (for crash loop detection)
|
||||||
|
* @param bool $preserveRestarting If true, return "restarting:unknown" instead of "degraded:unhealthy" for restarting containers
|
||||||
* @return string Status in colon format (e.g., "running:healthy")
|
* @return string Status in colon format (e.g., "running:healthy")
|
||||||
*/
|
*/
|
||||||
private function resolveStatus(
|
private function resolveStatus(
|
||||||
@@ -214,7 +226,8 @@ class ContainerStatusAggregator
|
|||||||
bool $hasPaused,
|
bool $hasPaused,
|
||||||
bool $hasDead,
|
bool $hasDead,
|
||||||
bool $hasDegraded,
|
bool $hasDegraded,
|
||||||
int $maxRestartCount
|
int $maxRestartCount,
|
||||||
|
bool $preserveRestarting = false
|
||||||
): string {
|
): string {
|
||||||
// Priority 1: Degraded containers from sub-resources (highest priority)
|
// Priority 1: Degraded containers from sub-resources (highest priority)
|
||||||
// If any service/application within a service stack is degraded, the entire stack is degraded
|
// If any service/application within a service stack is degraded, the entire stack is degraded
|
||||||
@@ -222,9 +235,11 @@ class ContainerStatusAggregator
|
|||||||
return 'degraded:unhealthy';
|
return 'degraded:unhealthy';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority 2: Restarting containers (degraded state)
|
// Priority 2: Restarting containers
|
||||||
|
// When preserveRestarting is true (for individual sub-resources), keep as "restarting"
|
||||||
|
// When false (for overall service status), mark as "degraded"
|
||||||
if ($hasRestarting) {
|
if ($hasRestarting) {
|
||||||
return 'degraded:unhealthy';
|
return $preserveRestarting ? 'restarting:unknown' : 'degraded:unhealthy';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority 3: Crash loop detection (exited with restart count > 0)
|
// Priority 3: Crash loop detection (exited with restart count > 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user