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

Scheduler Laravel Package

symfony/scheduler

Symfony Scheduler Component lets you define recurring and one-off tasks and run them via Symfony Messenger. Supports cron-like schedules, delays, and integration with transports and workers. See docs for configuration, commands, and usage.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:

    composer require symfony/scheduler
    

    Requires Symfony Messenger and PHP 8.4+ (Symfony 8.x requirement).

  2. Configure Messenger Transport: Define a transport (e.g., doctrine, amqp, or sync) in config/packages/messenger.yaml:

    framework:
        messenger:
            transports:
                async: '%env(MESSENGER_TRANSPORT_DSN)%'
            routing:
                'App\Message\YourMessage': async
    
  3. Create a Scheduled Task: Use the #[AsCronTask] or #[AsFrequencyTask] attribute on a command or message handler:

    use Symfony\Component\Scheduler\Attribute\AsCronTask;
    
    #[AsCronTask("0 0 * * *", name: "daily-report")]
    class GenerateDailyReportCommand extends Command
    {
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            // Task logic
            return Command::SUCCESS;
        }
    }
    
  4. Register the Schedule Provider: In config/services.yaml, tag your provider:

    services:
        App\Scheduler\DailyReportScheduleProvider:
            tags: [scheduler.schedule_provider]
    
  5. Run the Scheduler: Execute the scheduler worker:

    php bin/console messenger:consume async -vv
    

First Use Case: Cron-Like Task Scheduling

Replace a cron job with a Symfony Scheduler task:

#[AsCronTask("*/5 * * * *", name: "cleanup-temp-files")]
class CleanupTempFilesCommand extends Command
{
    public function __construct(private Filesystem $filesystem) {}

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->filesystem->remove($this->getTempDir());
        return Command::SUCCESS;
    }
}

Key: No external cron needed; Symfony handles execution via Messenger.


Where to Look First

  • Official Documentation: Setup, attributes, and configuration.
  • #[AsCronTask] and #[AsFrequencyTask]: Core attributes for defining schedules.
  • ScheduleProviderInterface: For dynamic schedules (e.g., runtime-generated cron jobs).
  • Messenger Transports: Ensure your transport (e.g., doctrine, amqp) is configured in messenger.yaml.
  • New in v8.1.0-BETA2: Debugging improvements with checkpoint-based scheduling in debug:scheduler.

Implementation Patterns

1. Declarative Scheduling with Attributes

Use attributes for clean, type-safe scheduling:

#[AsCronTask("0 12 * * 1", name: "weekly-backup")]
class WeeklyBackupCommand extends Command
{
    // ...
}

Pros: IDE-friendly, no XML/YAML. Cons: Less flexible for dynamic schedules (use ScheduleProviderInterface instead).


2. Dynamic Schedules via ScheduleProviderInterface

For runtime-defined schedules (e.g., user-specific tasks):

use Symfony\Component\Scheduler\ScheduleProviderInterface;
use Symfony\Component\Scheduler\TriggerInterface;

class UserSpecificScheduleProvider implements ScheduleProviderInterface
{
    public function getSchedule(): array
    {
        return [
            'user-' . $userId => new CronTrigger('0 0 * * *', new Message('App\Message\ProcessUserData', ['userId' => $userId])),
        ];
    }
}

Register in services.yaml:

services:
    App\Scheduler\UserSpecificScheduleProvider:
        tags: [scheduler.schedule_provider]

3. Integrating with Symfony Messenger

Leverage Messenger’s transports (e.g., doctrine, amqp) for reliability:

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            async: 'doctrine://default?queue_name=scheduler'
        routing:
            'Symfony\Component\Scheduler\Message\ScheduleMessage': async

Key: Use ScheduleMessage for internal scheduler communication.


4. Handling Task Results and Events

Access command output or handle failures:

use Symfony\Component\Scheduler\Event\PostRunEvent;

class SchedulerListener
{
    public function onPostRun(PostRunEvent $event): void
    {
        if ($event->getExitCode() !== 0) {
            // Log failure or send alert
        }
    }
}

Register in services.yaml:

services:
    App\Scheduler\SchedulerListener:
        tags: [kernel.event_listener, scheduler.event_listener]

5. Workflow: From Development to Production

  1. Local Testing:
    php bin/console messenger:consume async -vv
    
  2. CI/CD: Ensure the scheduler worker runs in your deployment pipeline (e.g., Docker, Kubernetes).
  3. Monitoring: Use Symfony’s scheduler:list and scheduler:run commands.
    • New in v8.1.0-BETA2: debug:scheduler now uses checkpoints for accurate next-run calculations.

6. Laravel Workarounds (If You Must Use It)

Bridge Symfony Scheduler with Laravel via a custom Artisan command:

use Symfony\Component\Process\Process;

class RunSymfonyScheduler extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $process = new Process(['php', 'bin/console', 'messenger:consume', 'async']);
        $process->run();
        $output->write($process->getOutput());
        return $process->getExitCode();
    }
}

Register in app/Console/Kernel.php:

protected function schedule(Schedule $schedule)
{
    $schedule->command('run-symfony-scheduler')->everyMinute();
}

7. Leveraging New Features in v8.1.0-BETA2

Checkpoint-Based Debugging

The debug:scheduler command now uses stored checkpoints as the base date for calculating next runs, improving accuracy:

php bin/console debug:scheduler

Key: More reliable debugging for cron-based schedules.


Gotchas and Tips

Pitfalls

  1. PHP Version Mismatch:

    • Symfony 8.x requires PHP 8.4+; Laravel 11 maxes at 8.3.
    • Fix: Use Symfony 7.x (PHP 8.2+) if stuck on Laravel 10.
  2. Duplicate Schedule Names:

    • Symfony throws an error if two providers define the same schedule name.
    • Fix: Use unique names (e.g., app.daily-backup vs. user.daily-backup).
  3. Messenger Transport Misconfiguration:

    • If the transport fails (e.g., Doctrine connection down), tasks won’t run.
    • Fix: Monitor transport health with php bin/console messenger:failed:list.
  4. #[AsCronTask] Argument Issues:

    • Passing arrays to commands via attributes may fail.
    • Fix: Use #[AsFrequencyTask] with Message objects instead.
  5. Time Zone Awareness:

    • Cron expressions use the server’s time zone by default.
    • Fix: Set SYMFONY_CRON_TIMEZONE in .env:
      SYMFONY_CRON_TIMEZONE=America/New_York
      
  6. Command Alias Conflicts:

    • Ensure aliases do not conflict with existing commands.
    • Fix: Test aliases with php bin/console list --all.

Debugging Tips

  1. List All Schedules with Checkpoints:

    php bin/console debug:scheduler
    
    • New in v8.1.0-BETA2: Uses stored checkpoints for accurate next-run calculations.
  2. Run a Single Schedule:

    php bin/console scheduler:run "daily-report"
    
  3. Check Failed Tasks:

    php bin/console messenger:failed:list
    
  4. Enable Debug Logging: Add to config/packages/dev/monolog.yaml:

    handlers:
        scheduler
    
  5. Verify Checkpoint Storage: Ensure your transport (e.g., Doctrine) persists checkpoints correctly. For doctrine transport, check the failed and scheduled tables.


  1. Checkpoint-Based Scheduling Quirks:
    • If checkpoints are not stored correctly (e.g., transport failures), debug:scheduler may show incorrect next-run times.
    • Fix: Manually verify checkpoint storage in the database or configure a reliable transport (e.g., amqp).
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope