Skip to content

feat(applications): add configurable restart loop limit#9231

Open
ShadowArcanist wants to merge 2 commits intocoollabsio:nextfrom
ShadowArcanist:jean/add-restart-loop-limit
Open

feat(applications): add configurable restart loop limit#9231
ShadowArcanist wants to merge 2 commits intocoollabsio:nextfrom
ShadowArcanist:jean/add-restart-loop-limit

Conversation

@ShadowArcanist
Copy link
Copy Markdown
Member

@ShadowArcanist ShadowArcanist commented Mar 28, 2026

Changes

  • Added option to configure crash restart limits which helps to prevent application being stuck in a restart loop forever, by default the crash restart limit is set to 10

Note

  • Coolify already tracked restart counts but had no limit so application that gets into a crash restart loop will keep getting restarted forever.
  • Manual restarts and redeploys resets the restart counter so these actions won't increase the restart counter
  • If user have enabled the event "Container Status Changes" on notifications then Coolify will send notification when Coolify stops the application after the restart limit is reached.

Issues

Category

  • Improvement

Preview

UI

image

Notification:

image

AI Assistance

  • AI was used (please describe below)

If AI was used:

  • Tools used: Jean + Claude (Opus 4.6)
  • How extensively: every change on this PR (except the PR description)

Testing

Deployed crash loop example application and set the restart limit to 2, Coolify automatically stopped the application after it restarted 2 times. Also tested setting higher restart limit and it worked. Also tested restarting and redeploying the application to see if it triggers this restart limit feature and it didn't triggered it.

Contributor Agreement

Important

  • I have read and understood the contributor guidelines. If I have failed to follow any guideline, I understand that this PR may be closed without review.
  • I have searched existing issues and pull requests (including closed ones) to ensure this isn't a duplicate.
  • I have tested all the changes thoroughly with a local development instance of Coolify and I am confident that they will work as expected when a maintainer tests them.

@andrasbacsai
Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 30, 2026

Walkthrough

This PR introduces a maximum restart count feature for applications. A new database column max_restart_count (default 10) is added to the applications table via migration. The Application model casts this attribute as an integer. The Advanced Livewire component exposes a new maxRestartCount property with validation and a saveMaxRestartCount() action to persist configuration. The GetContainersStatus action now monitors restart counts and, when an application exceeds its configured threshold, dispatches StopApplication and notifies the team via the new ApplicationRestartLimitReached notification (supporting email, Discord, Telegram, Pushover, Slack, and webhook channels). A new email template communicates the automatic stop to users. The UI component displays the restart limit setting in the application advanced configuration panel.

I'll be back—to make sure your self-hosted applications don't restart themselves into a gluten-free taco dust storm. 🌮

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/Notifications/Application/RestartLimitReached.php`:
- Line 43: Replace the manual URL assembly in RestartLimitReached (the
assignment to $this->resource_url) with a call to the Application model's link()
method (use $this->resource->link()) and fall back to the current base_url()
construction if link() returns null; specifically update the assignment in
RestartLimitReached.php to prefer $this->resource->link() and only build
base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}"
(or use {$this->environment_name} if your fallback should mirror the example)
when link() is null so route changes are centralized in Application::link().

In
`@database/migrations/2026_03_27_000000_add_max_restart_count_to_applications_and_databases.php`:
- Around line 1-22: The migration filename indicates it should modify both
applications and databases but the migration class only alters the applications
table (methods up()/down() add/drop max_restart_count on 'applications'); either
rename the file to match its actual behavior (e.g., remove "_and_databases" so
it becomes add_max_restart_count_to_applications) or update the migration logic
to also add and drop the max_restart_count integer column (default 10, after
'restart_count') on the 'databases' table in both up() and down() so the
filename accurately reflects the changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f8400913-9e85-4a2f-a72a-a5df8ed4e56a

📥 Commits

Reviewing files that changed from the base of the PR and between 98569e4 and 886d014.

📒 Files selected for processing (7)
  • app/Actions/Docker/GetContainersStatus.php
  • app/Livewire/Project/Application/Advanced.php
  • app/Models/Application.php
  • app/Notifications/Application/RestartLimitReached.php
  • database/migrations/2026_03_27_000000_add_max_restart_count_to_applications_and_databases.php
  • resources/views/emails/application-restart-limit-reached.blade.php
  • resources/views/livewire/project/application/advanced.blade.php

if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = str($this->fqdn)->explode(',')->first();
}
$this->resource_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

I'll be back... with a refactoring suggestion for URL construction.

The URL is manually constructed here, but the Application model already has a link() method (line 452-463 in Application.php) that uses Laravel's named routes. Using the existing method would be more maintainable and DRY:

- $this->resource_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}";
+ $this->resource_url = $this->resource->link();

If the link() method can return null, you'd need a fallback:

$this->resource_url = $this->resource->link() ?? base_url()."/project/{$this->project_uuid}/{$this->environment_name}/application/{$this->resource->uuid}";

This way, if routes ever change, you only need to update one place. Like a good self-hosted infrastructure - single source of truth!

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/Notifications/Application/RestartLimitReached.php` at line 43, Replace
the manual URL assembly in RestartLimitReached (the assignment to
$this->resource_url) with a call to the Application model's link() method (use
$this->resource->link()) and fall back to the current base_url() construction if
link() returns null; specifically update the assignment in
RestartLimitReached.php to prefer $this->resource->link() and only build
base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}"
(or use {$this->environment_name} if your fallback should mirror the example)
when link() is null so route changes are centralized in Application::link().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants