Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Short Schedule Laravel Package

spatie/laravel-short-schedule

Run Laravel Artisan commands at sub-minute intervals (every second or even 0.5s). Adds a short-scheduler powered by a ReactPHP event loop, running separately from schedule:run so high-frequency tasks don’t block or get delayed.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**: Add the package via Composer:
   ```bash
   composer require spatie/laravel-short-schedule
  1. Publish Config (if needed): No config file is required by default, but you can publish one if you need to customize behavior:
    php artisan vendor:publish --provider="Spatie\ShortSchedule\ShortScheduleServiceProvider"
    
  2. Define Short Schedule: Add the shortSchedule method to your app/Console/Kernel.php:
    protected function shortSchedule(ShortSchedule $shortSchedule)
    {
        $shortSchedule->command('your-command')->everySecond();
    }
    
  3. Run the Scheduler: Start the short scheduler in production:
    php artisan short-schedule:run
    
    Use a process manager like Supervisor to keep it running persistently.

First Use Case

Schedule a command to run every 5 seconds:

ShortSchedule::command('your-command')->everySeconds(5);

Implementation Patterns

Core Workflow

  1. Define Tasks: Use the shortSchedule method in Kernel.php or the ShortSchedule facade in console.php to define tasks.
    // Kernel.php
    protected function shortSchedule(ShortSchedule $shortSchedule)
    {
        $shortSchedule->command('cache:clear')->everyMinutes(1);
    }
    
  2. Run Independently: The scheduler runs as a separate process (powered by ReactPHP), ensuring it doesn’t block Laravel’s native scheduler.
  3. Process Management: Each command runs in its own background process, preventing slow tasks from delaying others.

Common Patterns

  1. Sub-Second Precision:

    ShortSchedule::command('log:clean')->everySeconds(0.5); // Runs every half-second
    
  2. Shell Commands:

    ShortSchedule::exec('php artisan optimize')->everyHour();
    
  3. Constraints:

    • Time Constraints: Limit execution to business hours:
      ShortSchedule::command('sync-data')->between('09:00', '17:00')->everySecond();
      
    • Environment Constraints: Restrict to specific environments:
      ShortSchedule::command('deploy')->environments(['staging', 'production'])->everyMinute();
      
    • Conditional Execution: Use closures for dynamic logic:
      ShortSchedule::command('notify-users')->when(fn() => User::count() > 100)->everyMinute();
      
    • Overlap Prevention: Avoid overlapping executions:
      ShortSchedule::command('backup')->everyHour()->withoutOverlapping();
      
    • Maintenance Mode: Force execution even in maintenance mode:
      ShortSchedule::command('critical-task')->everySecond()->runInMaintenanceMode();
      
    • Single Server Execution: Ensure only one server runs the task:
      ShortSchedule::command('leader-election')->everyMinute()->onOneServer();
      
  4. Event Listeners: React to task execution (use queues for heavy logic):

    ShortScheduledTaskStarting::dispatch($command, $process);
    

Integration Tips

  • Queue Heavy Logic: Offload event handlers or constraints to queues to avoid blocking the ReactPHP loop.
  • Logging: Use Laravel’s logging or custom logs to track short-scheduled task executions.
  • Monitoring: Integrate with tools like Laravel Horizon or Prometheus to monitor task health.
  • Testing: Mock the scheduler in tests using ShortSchedule::fake() (if available) or test ReactPHP loops directly (see Spatie’s testing video).

Gotchas and Tips

Pitfalls

  1. Blocking the Loop:

    • Constraints (when, between) and event listeners run inside the ReactPHP loop. Heavy logic here will delay all tasks.
    • Fix: Offload to queues or optimize constraints (e.g., cache results of when closures).
    // Bad: Heavy logic in constraint
    ShortSchedule::command('slow-task')->when(fn() => heavyDatabaseQuery())->everySecond();
    
    // Good: Pre-compute or cache
    ShortSchedule::command('slow-task')->when(fn() => Cache::remember('task_condition', 60, fn() => heavyDatabaseQuery()))->everySecond();
    
  2. Memory Leaks:

    • Long-running tasks or memory leaks in child processes can bloat the worker.
    • Fix: Use the --lifetime flag to restart the worker periodically:
      php artisan short-schedule:run --lifetime=3600  # Restart every hour
      
  3. Supervisor Misconfiguration:

    • If using Supervisor, ensure the command is set to restart on failure:
      [program:short-schedule]
      command=php /path/to/artisan short-schedule:run --lifetime=3600
      autostart=true
      autorestart=true
      user=www-data
      numprocs=1
      stderr_logfile=/var/log/short-schedule.err.log
      stdout_logfile=/var/log/short-schedule.out.log
      
  4. Command Resolution:

    • If passing a class (e.g., ShortSchedule::command(MyCommand::class)), ensure the class is autoloaded and the handle() method exists.
    • Fix: Verify the class is registered in config/app.php under providers.
  5. Timezone Sensitivity:

    • The between method uses the server’s timezone. Ensure it matches your expectations.
    • Fix: Set the timezone explicitly in .env:
      APP_TIMEZONE=UTC
      
  6. Overlapping Tasks:

    • By default, tasks run regardless of previous executions. Use withoutOverlapping() to prevent this, but beware of race conditions in distributed environments.
    • Fix: Combine with onOneServer() for single-server deployments.

Debugging Tips

  1. Logs:

    • Check /var/log/short-schedule.out.log (or your Supervisor log path) for errors.
    • Enable debug mode in the scheduler:
      php artisan short-schedule:run --verbose
      
  2. Process Inspection:

    • List running processes to verify the scheduler is active:
      ps aux | grep short-schedule
      
    • Kill stale processes if needed:
      pkill -f short-schedule
      
  3. Testing:

    • Use ShortSchedule::fake() (if available) to mock the scheduler in tests.
    • For ReactPHP loops, test constraints and events in isolation:
      use Spatie\ShortSchedule\Tests\TestCase;
      
      public function test_constraint()
      {
          $this->assertTrue($this->app->make(ShortSchedule::class)->constraint()->evaluate());
      }
      
  4. Environment Issues:

    • Ensure the scheduler runs in the correct environment (e.g., production). Use the environments() constraint to restrict execution:
      ShortSchedule::command('task')->environments('production')->everySecond();
      

Extension Points

  1. Custom Constraints: Extend the Spatie\ShortSchedule\Constraints\Constraint class to create reusable constraints:

    namespace App\ShortSchedule\Constraints;
    
    use Spatie\ShortSchedule\Constraints\Constraint;
    
    class CustomConstraint extends Constraint
    {
        public function evaluate(): bool
        {
            return customLogic();
        }
    }
    

    Use it in schedules:

    ShortSchedule::command('task')->constraint(new CustomConstraint())->everySecond();
    
  2. Event Extensions: Listen to events like ShortScheduledTaskStarting to add pre/post-task logic:

    ShortScheduledTaskStarting::listen(function ($command, $process) {
        Log::info("Starting {$command} at " . now());
    });
    
  3. Process Lifecycle: Override the Spatie\ShortSchedule\ShortSchedule class to customize process creation (e.g., environment variables):

    $shortSchedule->command('task')->everySecond()->withOptions(['--env' => 'production']);
    
  4. ReactPHP Customization: For advanced use cases, extend the Spatie\ShortSchedule\ShortSchedule class to modify the ReactPHP loop behavior (e.g., custom timers or signals).

Pro Tips

  • Combine with Laravel Tasks: Use short scheduling for real-time tasks (e.g., WebSocket updates) and Laravel’s native scheduler for longer intervals (e.g., daily reports).
  • Rate Limiting: Use everySeconds(1) with withoutOverlapping() to create a simple rate limiter for external APIs.
  • Dynamic Scheduling: Rebuild the schedule dynamically by clearing and re-adding tasks:
    $shortSchedule->clear();
    $shortSchedule->command('dynamic-task')->everySeconds(config('
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony