-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Enhance scheduled tasks with improved retry and timeout features #7177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add retry configuration to CoolifyTask (3 tries, 600s timeout) - Add retry configuration to ScheduledTaskJob (3 tries, configurable timeout) - Add retry configuration to DatabaseBackupJob (2 tries) - Implement exponential backoff for all jobs (30s, 60s, 120s intervals) - Add failed() handlers with comprehensive error logging to scheduled-errors channel - Add execution tracking: started_at, retry_count, duration (decimal), error_details - Add configurable timeout field to scheduled tasks (60-3600s, default 300s) - Update UI to include timeout configuration in task creation/editing forms - Increase ScheduledJobManager lock expiration from 60s to 90s for high-load environments - Implement safe queue cleanup with restart vs runtime modes - Restart mode: aggressive cleanup (marks all processing jobs as failed) - Runtime mode: conservative cleanup (only marks jobs >12h as failed, skips deployments) - Add cleanup:redis --restart flag for system startup - Integrate cleanup into Dev.php init() for development environment - Increase scheduled-errors log retention from 7 to 14 days - Create comprehensive test suite (unit and feature tests) - Add TESTING_GUIDE.md with manual testing instructions Fixes issues with jobs failing after single attempt and "attempted too many times" errors
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
WalkthroughThe PR adds retry and timeout handling to scheduled task jobs (CoolifyTask, ScheduledTaskJob, DatabaseBackupJob) with configurable backoff strategies, introduces aggressive stuck job cleanup on startup via a new --restart flag in CleanupRedis, extends execution tracking with timestamp and retry count columns, and updates UI components and configuration to support timeout management. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Dev as Dev Command
participant Redis as Redis<br/>(via CleanupRedis)
participant Queue as Job Queue
participant Job as Job Handler
participant Log as Logger
User->>Dev: Run startup
Dev->>Redis: cleanup:redis --restart --clear-locks
Redis->>Redis: cleanupStuckJobs()<br/>(restart mode)
Redis->>Redis: Mark all processing/reserved<br/>jobs as failed
note over Redis: Log cleanup summary
Dev->>Queue: Initialize queue workers
Note over Queue: Ready for new jobs
User->>Queue: Dispatch ScheduledTaskJob
Queue->>Job: Execute job
alt Job succeeds
Job->>Job: Record finished_at,<br/>duration in task_log
Job-->>User: Success
else Job fails
Job->>Log: Log error to<br/>scheduled-errors
Job->>Job: Update task_log with<br/>error_details, retry_count
Job->>Job: Call backoff()<br/>for retry interval
Note over Job: Retry with [30, 60, 120]s<br/>intervals (up to 3 times)
alt Retries exhausted
Job->>Job: Call failed()
Job->>Log: Log permanent failure
Job->>Job: Update finished_at,<br/>notify team
Job-->>User: Permanent failure
else Retry succeeds
Job-->>User: Success after retry
end
end
sequenceDiagram
participant Admin as Admin
participant UI as Scheduled Task UI
participant Component as Livewire Component
participant Model as ScheduledTask Model
Admin->>UI: Create/Edit Task
Admin->>UI: Set timeout field<br/>(60–3600 seconds)
note over UI: Validation enforced<br/>in component
Admin->>UI: Save task
Component->>Component: Validate timeout<br/>integer, range check
alt Validation passes
Component->>Model: Persist timeout<br/>to database
Model->>Model: Cast as integer
Component->>Admin: Show success
else Validation fails
Component->>Admin: Show error message
end
Admin->>UI: View existing task
Component->>Model: Load timeout from DB
Model->>Component: Return timeout (cast int,<br/>default 300 if null)
UI->>Admin: Display timeout field<br/>with loaded value
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas requiring extra attention:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/Jobs/ScheduledTaskJob.php (1)
44-45: Prevent fatal logging when server isn't initialized
$this->serveris typed as non-nullable and only assigned after we hit the container lookup. If anything throws before that assignment (e.g. the execution insert or retrieving the destination), the catch/failed handlers will try to read$this->serverand PHP will raise “Typed property ... must not be accessed before initialization,” losing the original error. Make the property nullable (same for the log reads) so we can safely log early failures.- public Server $server; + public ?Server $server = null; @@ - 'server' => $this->server->name ?? 'unknown', + 'server' => $this->server?->name ?? 'unknown', @@ - 'server' => $this->server->name ?? 'unknown', + 'server' => $this->server?->name ?? 'unknown',app/Jobs/DatabaseBackupJob.php (1)
47-50: Initialize optional dependencies before failed() logging
$serverand$databaseare declared as non-nullable typed properties, but failures can happen before they’re assigned (e.g. missing relations or errors pulling metadata). Whenfailed()runs it accesses them, which will trigger “Typed property … must not be accessed before initialization” and mask the real failure. Make them nullable with a default null so the logging path stays safe.- public Server $server; - - public StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase $database; + public ?Server $server = null; + + public StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase|null $database = null;
🧹 Nitpick comments (1)
app/Models/ScheduledTask.php (1)
13-13: Consider defining explicit$fillablefor mass assignment protection.Using
$guarded = []allows all attributes to be mass-assigned. Consider defining an explicit$fillablearray to be more restrictive and secure.Based on coding guidelines.
Apply this diff to add explicit fillable attributes:
- protected $guarded = []; + protected $fillable = [ + 'name', + 'command', + 'frequency', + 'container', + 'enabled', + 'timeout', + 'application_id', + 'service_id', + 'team_id', + ];
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (21)
TESTING_GUIDE.md(1 hunks)app/Console/Commands/CleanupRedis.php(3 hunks)app/Console/Commands/Dev.php(1 hunks)app/Console/Commands/Init.php(1 hunks)app/Jobs/CoolifyTask.php(2 hunks)app/Jobs/DatabaseBackupJob.php(3 hunks)app/Jobs/ScheduledJobManager.php(1 hunks)app/Jobs/ScheduledTaskJob.php(4 hunks)app/Livewire/Project/Shared/ScheduledTask/Add.php(3 hunks)app/Livewire/Project/Shared/ScheduledTask/Show.php(2 hunks)app/Models/ScheduledTask.php(1 hunks)app/Models/ScheduledTaskExecution.php(1 hunks)config/logging.php(1 hunks)database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.php(1 hunks)database/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php(1 hunks)resources/views/livewire/project/shared/scheduled-task/add.blade.php(1 hunks)resources/views/livewire/project/shared/scheduled-task/show.blade.php(1 hunks)templates/service-templates-latest.json(3 hunks)templates/service-templates.json(3 hunks)tests/Feature/CoolifyTaskRetryTest.php(1 hunks)tests/Unit/ScheduledJobsRetryConfigTest.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (25)
app/Jobs/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Queueable background work should be implemented as Jobs under app/Jobs; Actions may expose asJob to dispatch
app/Jobs/**/*.php: Queue jobs should implement ShouldQueue and define retry strategy (tries, maxExceptions, backoff)
Queue jobs must handle success/failure state updates and broadcast corresponding events; implement failed(Throwable) for final failure handlingQueue jobs should update status, wrap external calls in try/catch, set failure status on exceptions, and rethrow
Files:
app/Jobs/ScheduledJobManager.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpapp/Jobs/DatabaseBackupJob.php
app/Jobs/*.php
📄 CodeRabbit inference engine (.cursor/rules/deployment-architecture.mdc)
Implement background deployment, monitoring, backup, and notification work as Laravel Job classes under app/Jobs
Files:
app/Jobs/ScheduledJobManager.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpapp/Jobs/DatabaseBackupJob.php
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
**/*.php: Follow PSR-12 coding standards for all PHP code
Format PHP code with Laravel Pint configuration
Run static analysis with PHPStan to ensure type safety in PHP code
Document complex methods with PHPDoc blocks including parameters, return types, and thrown exceptions
**/*.php: Follow PSR-12 PHP coding standards across the codebase
Prefer eager loading and query optimization to prevent N+1 issues in database interactions
Use Laravel best practices for structure, services, and policies
**/*.php: Always use curly braces for control structures in PHP, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors
Always declare explicit return types for functions and methods; add appropriate parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline code comments for very complex logic
When documenting arrays, add useful array shape types in PHPDoc where appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)
Files:
app/Jobs/ScheduledJobManager.phpapp/Models/ScheduledTaskExecution.phpconfig/logging.phpdatabase/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpapp/Models/ScheduledTask.phpapp/Console/Commands/CleanupRedis.phptests/Feature/CoolifyTaskRetryTest.phpapp/Console/Commands/Dev.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpresources/views/livewire/project/shared/scheduled-task/show.blade.phpapp/Console/Commands/Init.phpapp/Livewire/Project/Shared/ScheduledTask/Show.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.phptests/Unit/ScheduledJobsRetryConfigTest.phpapp/Livewire/Project/Shared/ScheduledTask/Add.phpapp/Jobs/DatabaseBackupJob.phpresources/views/livewire/project/shared/scheduled-task/add.blade.php
app/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
Use database transactions to group related write operations for consistency in services/controllers/jobs
Files:
app/Jobs/ScheduledJobManager.phpapp/Models/ScheduledTaskExecution.phpapp/Models/ScheduledTask.phpapp/Console/Commands/CleanupRedis.phpapp/Console/Commands/Dev.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpapp/Console/Commands/Init.phpapp/Livewire/Project/Shared/ScheduledTask/Show.phpapp/Livewire/Project/Shared/ScheduledTask/Add.phpapp/Jobs/DatabaseBackupJob.php
app/Jobs/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Implement background jobs under app/Jobs
Files:
app/Jobs/ScheduledJobManager.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpapp/Jobs/DatabaseBackupJob.php
app/Models/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Keep Eloquent domain models in app/Models; models represent core entities (e.g., Application, Server, Service, Team, Project)
app/Models/**/*.php: Define $fillable for mass assignment protection in Eloquent models
Use $casts for attribute casting (e.g., arrays, enums, datetimes) in Eloquent models
Define relationships using Eloquent relation return types (e.g., BelongsTo, HasMany)
app/Models/**/*.php: Define Eloquent relationships using proper relationship methods with return type hints
Prefer Eloquent ORM and relationships over raw queries or DB:: calls
Prevent N+1 queries by using eager loading when appropriate
When creating new models, also create useful factories and seeders
Files:
app/Models/ScheduledTaskExecution.phpapp/Models/ScheduledTask.php
app/Models/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Place domain models under app/Models
Files:
app/Models/ScheduledTaskExecution.phpapp/Models/ScheduledTask.php
app/Models/*.php
📄 CodeRabbit inference engine (.cursor/rules/database-patterns.mdc)
app/Models/*.php: When adding new database columns, update the model's $fillable array to allow mass assignment (e.g., for Model::create() and $model->update())
Use UUID primary keys via HasUuids for distributed systems
Enable soft deletes on models that require audit trails using SoftDeletes
Log model activity using the Spatie LogsActivity trait where auditing is required
Define explicit Eloquent relationships (belongsTo/hasMany/etc.) for navigable associations used by queries and eager loading
Files:
app/Models/ScheduledTaskExecution.phpapp/Models/ScheduledTask.php
config/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Keep application settings in Laravel config files under config/ and load them via config()
Application configuration should reside in config/*.php files
Files:
config/logging.php
database/migrations/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
Create descriptive migrations with proper foreign keys, cascading deletes, indexes, and timestamps
database/migrations/**/*.php: When modifying a column in a migration, re-specify all previously defined attributes to avoid dropping them
Use php artisan make: commands (e.g., make:migration) to create new Laravel files; pass --no-interaction and appropriate options
Files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
database/migrations/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Keep database migrations under database/migrations
Files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
database/migrations/*.php
📄 CodeRabbit inference engine (.cursor/rules/database-patterns.mdc)
database/migrations/*.php: Place all Laravel database migrations under database/migrations and follow standard Schema::create/Schema::table structure
Always provide both up() and down() methods in migrations to ensure rollback support
Use incremental, reversible migrations; separate structural changes from data migrations when appropriate
Create appropriate indexes: primary keys, foreign key indexes, composite indexes for common queries, and unique constraints for business rules
Files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
app/Console/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Define Artisan console commands in app/Console
Files:
app/Console/Commands/CleanupRedis.phpapp/Console/Commands/Dev.phpapp/Console/Commands/Init.php
tests/Feature/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Place integration/request lifecycle tests under tests/Feature
tests/Feature/**/*.php: Feature tests (tests/Feature) may use database connections (migrations, models, factories)
Feature tests that touch the database must use the RefreshDatabase trait
Files:
tests/Feature/CoolifyTaskRetryTest.php
tests/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
Write feature tests for API endpoints using Pest; mock external services and assert JSON responses and side effects
Add tests validating that components respect authorization (e.g., unauthorized users see disabled inputs; checkbox instantSave becomes false)
Include security tests covering SQL injection resistance, XSS validation, and enforcement of team isolation (403 on cross-team access).
Write tests using Pest (feature/unit) and include Laravel Dusk for browser scenarios as needed
Prefer Pest PHP as the primary testing framework for writing tests
Files:
tests/Feature/CoolifyTaskRetryTest.phptests/Unit/ScheduledJobsRetryConfigTest.php
tests/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Keep automated tests (Pest/Dusk) under tests
Files:
tests/Feature/CoolifyTaskRetryTest.phptests/Unit/ScheduledJobsRetryConfigTest.php
tests/{Feature,Unit}/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
tests/{Feature,Unit}/**/*.php: All tests must be written using Pest and live under tests/Feature or tests/Unit
Use specific response assertion helpers (e.g., assertForbidden, assertNotFound) instead of generic assertStatus
Use datasets in Pest to reduce duplication where suitable (e.g., validation tests)
Write or update unit/feature tests for every change and run the affected tests
Files:
tests/Feature/CoolifyTaskRetryTest.phptests/Unit/ScheduledJobsRetryConfigTest.php
resources/views/**/*.blade.php
📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)
Use semantic Tailwind CSS classes and consistent spacing in Blade templates
resources/views/**/*.blade.php: In Blade views, prefer using x-forms components with canGate and :canResource instead of wrapping elements in @can/@else blocks
Remove legacy @can/@else blocks around individual form inputs/buttons and migrate to the single-line component pattern
Choose gates consistently in views: use update for configuration changes, deploy for operational actions, view for read-only access, and delete for destructive actions
Always pass the specific resource to :canResource (e.g., :canResource="$application", "$service", "$server"), and use team context for creation permissions (e.g., :canResource="auth()->user()->currentTeam" with canGate="createAnyResource")
Only set autoDisable="false" when also providing explicit :disabled logic on the component
Use single-line authorized components for forms (inputs, selects, checkboxes, buttons) to reduce duplication (e.g., <x-forms.input canGate="update" :canResource="$resource" ... />)
resources/views/**/*.blade.php: In Blade views, prefer x-forms.* components with canGate and :canResource for authorization (autoDisable defaults to true) instead of manual permission blocks.
Do not wrap x-forms.* components in @can/@else to toggle disabled state; use component-level canGate/:canResource instead.
For custom interactive components not using x-forms.* (e.g., Alpine.js widgets), wrap with @can('gate', $resource) and provide a disabled/readonly fallback in @else with opacity-50 and cursor-not-allowed styling.
resources/views/**/*.blade.php: Prefer named routes and the route() helper when generating links in views
Dispatch events using $this->dispatch() (not emit/dispatchBrowserEvent) in Livewire 3 templates/components
Do not manually include Alpine.js; Livewire 3 bundles Alpine with required plugins
Files:
resources/views/livewire/project/shared/scheduled-task/show.blade.phpresources/views/livewire/project/shared/scheduled-task/add.blade.php
resources/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Store frontend assets and views under resources
Files:
resources/views/livewire/project/shared/scheduled-task/show.blade.phpresources/views/livewire/project/shared/scheduled-task/add.blade.php
resources/views/livewire/**/*.blade.php
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
Livewire components must have a single root element; use wire:key in loops and wire:loading/wire:dirty for UX
Files:
resources/views/livewire/project/shared/scheduled-task/show.blade.phpresources/views/livewire/project/shared/scheduled-task/add.blade.php
resources/**/*.{blade.php,vue}
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
Use Tailwind gap utilities for spacing lists instead of margins when listing items
Files:
resources/views/livewire/project/shared/scheduled-task/show.blade.phpresources/views/livewire/project/shared/scheduled-task/add.blade.php
app/Livewire/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Define Livewire components in app/Livewire and keep HTTP/UI concerns there
app/Livewire/**/*.php: Livewire components must authorize access in mount and before actions that mutate state
Expose only necessary public typed properties and register event listeners via the $listeners array in Livewire componentsPlace Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)
Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()
Files:
app/Livewire/Project/Shared/ScheduledTask/Show.phpapp/Livewire/Project/Shared/ScheduledTask/Add.php
app/Livewire/**
📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)
Implement frontend components as Livewire classes under app/Livewire
Files:
app/Livewire/Project/Shared/ScheduledTask/Show.phpapp/Livewire/Project/Shared/ScheduledTask/Add.php
{app/Http/Controllers/**/*.php,app/Livewire/**/*.php}
📄 CodeRabbit inference engine (.cursor/rules/README.mdc)
Authorize sensitive actions with policies (e.g., $this->authorize('deploy', $model)) before invoking services
Files:
app/Livewire/Project/Shared/ScheduledTask/Show.phpapp/Livewire/Project/Shared/ScheduledTask/Add.php
tests/Unit/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)
Place unit tests under tests/Unit and keep them focused on individual classes/methods
tests/Unit/**/*.php: Unit tests (tests/Unit) must not use database connections or model factories
Unit tests must use mocking for models and external dependencies
Files:
tests/Unit/ScheduledJobsRetryConfigTest.php
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Use Redis-backed queues with Horizon, batch jobs when appropriate, and implement retry handling for failed jobs
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Jobs/**/*.php : Queue jobs should implement ShouldQueue and define retry strategy (tries, maxExceptions, backoff)
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Models/**/*.php : Use $casts for attribute casting (e.g., arrays, enums, datetimes) in Eloquent models
Applied to files:
app/Models/ScheduledTaskExecution.phpapp/Models/ScheduledTask.php
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to database/migrations/**/*.php : Create descriptive migrations with proper foreign keys, cascading deletes, indexes, and timestamps
Applied to files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
📚 Learning: 2025-10-15T09:14:50.127Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/database-patterns.mdc:0-0
Timestamp: 2025-10-15T09:14:50.127Z
Learning: Applies to database/migrations/*.php : Always provide both up() and down() methods in migrations to ensure rollback support
Applied to files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to database/migrations/**/*.php : When modifying a column in a migration, re-specify all previously defined attributes to avoid dropping them
Applied to files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
📚 Learning: 2025-10-15T09:14:50.127Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/database-patterns.mdc:0-0
Timestamp: 2025-10-15T09:14:50.127Z
Learning: Applies to database/migrations/*.php : Use incremental, reversible migrations; separate structural changes from data migrations when appropriate
Applied to files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
📚 Learning: 2025-10-15T09:14:50.127Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/database-patterns.mdc:0-0
Timestamp: 2025-10-15T09:14:50.127Z
Learning: Applies to database/migrations/*.php : Place all Laravel database migrations under database/migrations and follow standard Schema::create/Schema::table structure
Applied to files:
database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.phpdatabase/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php
📚 Learning: 2025-08-27T14:59:11.004Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Use Redis-backed queues with Horizon, batch jobs when appropriate, and implement retry handling for failed jobs
Applied to files:
app/Console/Commands/CleanupRedis.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpTESTING_GUIDE.md
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to tests/{Feature,Unit}/**/*.php : Write or update unit/feature tests for every change and run the affected tests
Applied to files:
tests/Feature/CoolifyTaskRetryTest.php
📚 Learning: 2025-10-15T09:17:35.563Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/testing-patterns.mdc:0-0
Timestamp: 2025-10-15T09:17:35.563Z
Learning: Applies to tests/Feature/**/*.php : Feature tests (tests/Feature) may use database connections (migrations, models, factories)
Applied to files:
tests/Feature/CoolifyTaskRetryTest.php
📚 Learning: 2025-10-15T09:17:35.563Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/testing-patterns.mdc:0-0
Timestamp: 2025-10-15T09:17:35.563Z
Learning: Applies to tests/Feature/**/*.php : Feature tests that touch the database must use the RefreshDatabase trait
Applied to files:
tests/Feature/CoolifyTaskRetryTest.php
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Jobs/**/*.php : Queue jobs should implement ShouldQueue and define retry strategy (tries, maxExceptions, backoff)
Applied to files:
tests/Feature/CoolifyTaskRetryTest.phpapp/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phptests/Unit/ScheduledJobsRetryConfigTest.phpTESTING_GUIDE.mdapp/Jobs/DatabaseBackupJob.php
📚 Learning: 2025-10-15T09:13:00.453Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/README.mdc:0-0
Timestamp: 2025-10-15T09:13:00.453Z
Learning: Applies to app/Jobs/**/*.php : Queue jobs should update status, wrap external calls in try/catch, set failure status on exceptions, and rethrow
Applied to files:
app/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phptests/Unit/ScheduledJobsRetryConfigTest.phpTESTING_GUIDE.mdapp/Jobs/DatabaseBackupJob.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Jobs/*.php : Implement background deployment, monitoring, backup, and notification work as Laravel Job classes under app/Jobs
Applied to files:
app/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpTESTING_GUIDE.mdapp/Jobs/DatabaseBackupJob.php
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Jobs/**/*.php : Queue jobs must handle success/failure state updates and broadcast corresponding events; implement failed(Throwable) for final failure handling
Applied to files:
app/Jobs/ScheduledTaskJob.phpapp/Jobs/CoolifyTask.phpapp/Jobs/DatabaseBackupJob.php
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Use queued jobs implementing ShouldQueue for time-consuming operations
Applied to files:
app/Jobs/ScheduledTaskJob.phpapp/Jobs/DatabaseBackupJob.php
📚 Learning: 2025-08-27T14:59:11.004Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Applies to app/Jobs/**/*.php : Queueable background work should be implemented as Jobs under app/Jobs; Actions may expose asJob to dispatch
Applied to files:
app/Jobs/CoolifyTask.phpapp/Jobs/DatabaseBackupJob.php
🪛 LanguageTool
TESTING_GUIDE.md
[style] ~201-~201: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ted manually ✅ - [ ] CoolifyTask tested manually (server validation, container ops, or d...
(ADVERB_REPETITION_PREMIUM)
🔇 Additional comments (18)
templates/service-templates.json (1)
976-985: Verify scope alignment: Service template categorization vs. scheduled task improvements.The PR description focuses on retry/timeout enhancements, error logging, and transient failure handling for scheduled tasks. However, this file updates service template categorization and tags to align with analytics classification. While the AI summary notes this as part of a "broader shift to analytics-driven categorization," the connection to scheduled task improvements is unclear.
Clarify whether these template changes are intentional for this PR or should be split into a separate issue.
Also applies to: 3667-3676
templates/service-templates-latest.json (2)
976-988: Verify alignment: service template changes vs. PR objectives on scheduled tasks.The PR objectives emphasize enhanced retry logic, configurable timeouts, and improved error logging for scheduled tasks. However, this file contains only service template metadata updates (tag/category changes and Docker Compose configurations) with no apparent connection to scheduled task retry/timeout improvements. This suggests either the wrong file was provided for review, or the AI summary is misaligned with the actual PR scope.
Please clarify:
- How do these service template changes relate to the scheduled task retry/timeout enhancements described in the PR objectives?
- Are there other files in this PR that contain the actual scheduled task job logic (e.g., app/Jobs/CoolifyTask.php, ScheduledTaskJob.php, DatabaseBackupJob.php)?
3667-3667: Base64-encoded compose configuration cannot be visually reviewed.Line 3667 replaces the "rybbit" compose field with a base64-encoded string that is too large to decode and verify in context. If this represents a significant update to the service configuration, consider:
- Providing the decoded YAML in a separate supporting document for reviewability
- Explicitly documenting what changed in the Compose spec (e.g., added services, new environment variables, updated health checks)
- Ensuring the encoded content has been validated independently
Can you provide the decoded Docker Compose configuration for the rybbit entry so the changes can be properly reviewed for correctness, security, and alignment with retry/timeout features mentioned in the PR objectives?
Also applies to: 3676-3676
app/Models/ScheduledTask.php (1)
15-21: LGTM! Proper attribute casting.The casts are correctly defined for the new timeout field and existing enabled field.
config/logging.php (1)
129-134: LGTM! Improved logging configuration for scheduled errors.The changes appropriately increase log retention to 14 days and set the level to warning, which is suitable for monitoring task failures while reducing log verbosity.
app/Livewire/Project/Shared/ScheduledTask/Show.php (2)
43-44: LGTM! Well-defined timeout property.The timeout property is properly validated with appropriate constraints (60-3600 seconds) and a sensible default of 300 seconds.
91-115: LGTM! Proper bidirectional data synchronization.The
syncDatamethod correctly handles both directions:
- When saving (
toModel = true), it persists the timeout to the model- When loading (
toModel = false), it initializes from the model with a fallback defaultresources/views/livewire/project/shared/scheduled-task/add.blade.php (1)
7-9: LGTM! Clear and user-friendly timeout input.The timeout field is well-positioned with helpful guidance text that explains the acceptable range and default value.
resources/views/livewire/project/shared/scheduled-task/show.blade.php (1)
38-39: LGTM! Consistent timeout input with edit form.The timeout field is properly configured and consistent with the add form, providing a cohesive user experience.
tests/Feature/CoolifyTaskRetryTest.php (2)
10-40: LGTM! Well-structured dispatch test.The test properly validates CoolifyTask dispatch with appropriate setup and assertions.
42-70: LGTM! Comprehensive retry configuration validation.The test thoroughly validates all retry-related properties (tries, maxExceptions, timeout) and the backoff sequence, ensuring the job is configured correctly.
app/Livewire/Project/Shared/ScheduledTask/Add.php (4)
37-37: LGTM! Properly initialized timeout property.The timeout property is correctly typed and initialized with a sensible default value.
39-53: LGTM! Comprehensive validation rules.The validation rules and attributes for timeout are properly defined and consistent with the Show component.
102-130: LGTM! Proper task persistence.The timeout is correctly assigned when saving the scheduled task.
132-139: LGTM! Proper form reset.The clear method correctly resets the timeout to its default value.
tests/Unit/ScheduledJobsRetryConfigTest.php (3)
7-22: LGTM! Thorough CoolifyTask configuration validation.The test uses reflection to verify both the presence and default values of retry-related properties and methods.
24-40: LGTM! ScheduledTaskJob retry validation.The test properly validates retry configuration including the timeout property specific to ScheduledTaskJob (300 seconds, matching the UI default).
42-56: LGTM! DatabaseBackupJob configuration check.The test correctly validates DatabaseBackupJob's retry properties with appropriate default values (tries=2, maxExceptions=1).
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…d add execution ID for timeout handling
…d database backups during startup
|
Hi @andrasbacsai, we use Coolify and scheduled tasks at work. |
Summary by CodeRabbit
Release Notes
New Features
Improvements
Documentation
Fixes