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

Symfony Worker Laravel Package

alexlcdee/symfony-worker

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation

    composer require alexlcdee/symfony-worker
    

    (Note: Requires Symfony Console and FrameworkBundle, so ensure compatibility with Laravel’s Symfony components.)

  2. Basic Worker Command Create a custom command extending SymfonyWorkerCommand:

    // app/Console/Commands/ProcessWorker.php
    namespace App\Console\Commands;
    
    use Alexlcdee\SymfonyWorker\SymfonyWorkerCommand;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class ProcessWorker extends SymfonyWorkerCommand
    {
        protected function configure()
        {
            $this->setName('worker:process')
                 ->setDescription('Process background jobs');
        }
    
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $this->run(function () {
                // Your job logic here (e.g., queue processing)
                $output->writeln('Processing job...');
            });
        }
    }
    
  3. Register Command Add to app/Console/Kernel.php:

    protected $commands = [
        \App\Console\Commands\ProcessWorker::class,
    ];
    
  4. Run the Worker

    php artisan worker:process
    

    (Use --daemon flag for background execution: php artisan worker:process --daemon)


First Use Case: Queue Worker

Replace Laravel’s default queue worker with this package for Symfony-style workers:

// app/Console/Commands/QueueWorker.php
use Illuminate\Queue\Worker;
use Symfony\Component\Process\Process;

class QueueWorker extends SymfonyWorkerCommand
{
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this = new Worker($this->app->queue(), $this->app->make('events'));
        $this->run(function () use ($worker) {
            $worker->daemon('default', function () {
                $worker->run();
            });
        });
    }
}

Implementation Patterns

1. Worker Lifecycle Management

  • Daemon Mode: Use --daemon to run workers in the background (requires pcntl extension).
    php artisan worker:process --daemon --pid=/tmp/worker.pid
    
  • Graceful Shutdown: Handle SIGTERM/SIGINT via Symfony’s Process signals:
    $this->run(function () {
        pcntl_signal(SIGTERM, function () {
            $this->getOutput()->writeln('Shutting down...');
            exit(0);
        });
    });
    

2. Integration with Laravel Queues

  • Custom Job Processing:
    $this->run(function () {
        while ($job = $this->app->queue()->getNextJob()) {
            $job->payload();
            $this->getOutput()->writeln('Processed job: ' . $job->resolveName());
        }
    });
    
  • Batch Processing:
    $this->run(function () {
        $jobs = $this->app->queue()->getJobs(['default']);
        foreach ($jobs as $job) {
            $job->fire();
        }
    });
    

3. Logging and Monitoring

  • Symfony Logger Integration:
    $this->run(function () {
        $logger = $this->getApplication()->getLogger();
        $logger->info('Worker started');
    });
    
  • Custom Output: Override getOutput() to use Laravel’s log channel:
    protected function getOutput()
    {
        return new SymfonyOutput($this->app->make('log')->channel('worker'));
    }
    

4. Worker Pools

  • Parallel Workers: Use Symfony’s Process to spawn multiple workers:
    $this->run(function () {
        $processes = [];
        for ($i = 0; $i < 4; $i++) {
            $process = new Process(['php', 'artisan', 'worker:process']);
            $process->start();
            $processes[] = $process;
        }
        foreach ($processes as $p) $p->wait();
    });
    

Gotchas and Tips

Pitfalls

  1. Symfony Dependency Conflicts:

    • The package requires Symfony 5.0 components, which may conflict with Laravel’s Symfony versions.
    • Fix: Use symfony/console and symfony/framework-bundle explicitly in composer.json:
      "extra": {
          "laravel": {
              "dont-discover": ["symfony-worker"]
          }
      }
      
  2. Daemon Mode Requires pcntl:

    • --daemon flag fails without the pcntl extension.
    • Fix: Install php-pcntl or use supervisor for process management.
  3. No Built-in Retry Logic:

    • Unlike Laravel’s queue worker, this package lacks retry mechanisms.
    • Workaround: Implement manually:
      $attempts = 0;
      $this->run(function () use (&$attempts) {
          try {
              $job->fire();
              $attempts = 0;
          } catch (\Exception $e) {
              if ($attempts++ < 3) sleep(1);
              else throw $e;
          }
      });
      
  4. Signal Handling Quirks:

    • Symfony’s Process signals may not propagate correctly in Laravel’s context.
    • Tip: Use pcntl directly for reliability:
      pcntl_signal(SIGTERM, function () {
          $this->getOutput()->writeln('Terminating...');
          exit(128 + SIGTERM);
      });
      

Debugging Tips

  • Check Worker PID: If using --daemon, verify the PID file:
    cat /tmp/worker.pid
    kill $(cat /tmp/worker.pid)
    
  • Symfony Event Dispatcher: Bind to console.terminate for cleanup:
    $this->getApplication()->getDispatcher()->addListener('console.terminate', function () {
        $this->getOutput()->writeln('Cleanup tasks...');
    });
    

Extension Points

  1. Custom Worker Classes: Extend SymfonyWorkerCommand to add domain-specific logic:

    class EmailWorker extends SymfonyWorkerCommand
    {
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $this->run(function () {
                Mail::queue(...);
            });
        }
    }
    
  2. Hooks for Pre/Post Execution: Override initialize() and terminate():

    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->getOutput()->writeln('Initializing worker...');
    }
    
    protected function terminate(InputInterface $input, OutputInterface $output, $code = 0)
    {
        $this->getOutput()->writeln('Worker stopped with code: ' . $code);
    }
    
  3. Environment-Specific Config: Use Laravel’s config to toggle worker behavior:

    if ($this->app->config->get('worker.enabled')) {
        $this->run(function () { /* ... */ });
    }
    
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.
graham-campbell/flysystem
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/opensearch-client
directorytree/opensearch-adapter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin