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

Daemon Bundle Laravel Package

code-meme/daemon-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies Ensure pcntl is enabled in your PHP binary. For Ubuntu/Debian:

    sudo apt-get install php-pcntl
    

    Restart your web server and PHP-FPM if applicable.

  2. Add Bundle to composer.json

    {
        "require": {
            "code-meme/daemon-bundle": "dev-master"
        }
    }
    

    Run composer update.

  3. Register Bundle Add to config/bundles.php:

    return [
        // ...
        CodeMeme\DaemonBundle\CodeMemeDaemonBundle::class => ['all' => true],
    ];
    
  4. First Daemon Command Create a console command extending DaemonCommand:

    // src/Command/MyDaemonCommand.php
    namespace App\Command;
    
    use CodeMeme\DaemonBundle\Command\DaemonCommand;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class MyDaemonCommand extends DaemonCommand
    {
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            while (true) {
                $output->writeln('Running daemon task...');
                sleep(10);
            }
        }
    }
    
  5. Run the Daemon

    php bin/console my:daemon
    

Implementation Patterns

Workflows

  1. Daemonizing Existing Commands Convert any Command into a daemon by extending DaemonCommand and overriding execute(). Example:

    class BackgroundProcessorCommand extends DaemonCommand
    {
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            while (!$this->isTerminated()) {
                $this->processQueue();
                sleep(5);
            }
        }
    }
    
  2. Signal Handling Leverage built-in signal handling (e.g., SIGTERM, SIGINT) via isTerminated():

    while (!$this->isTerminated()) {
        // Long-running task
    }
    
  3. Logging Use Symfony’s logger in execute():

    $this->getLogger()->info('Daemon started');
    
  4. Configuration Inject services via constructor or getContainer():

    public function __construct(private MyService $service) {}
    
  5. Supervisor Integration Configure Supervisor to manage daemons (e.g., auto-restart on crash):

    [program:my_daemon]
    command=php /path/to/bin/console my:daemon
    autostart=true
    autorestart=true
    user=www-data
    

Gotchas and Tips

Pitfalls

  1. pcntl Requirement

    • Error: FatalErrorException: Class 'pcntl_signal' not found.
    • Fix: Ensure php-pcntl is installed and enabled in php.ini (extension=pcntl).
  2. Permissions

    • Daemons run with limited privileges. Use setuid() or configure Supervisor to run as a specific user.
    • Tip: Test with sudo -u www-data php bin/console my:daemon to debug permission issues.
  3. Zombie Processes

    • If the daemon crashes, orphaned processes may linger.
    • Fix: Use Supervisor or implement cleanup in terminate():
      protected function terminate(InputInterface $input, OutputInterface $output)
      {
          posix_kill(posix_getpid(), SIGTERM);
      }
      
  4. Logging to File

    • Console output may not persist. Redirect logs to a file:
      $output = new StreamOutput(fopen('daemon.log', 'a'));
      $this->execute($input, $output);
      
  5. Debugging

    • Tip: Add a debug flag to dump state:
      if ($input->getOption('debug')) {
          var_dump($this->getContainer()->getParameter('some_param'));
      }
      

Tips

  1. Graceful Shutdown Override terminate() to handle cleanup:

    protected function terminate(InputInterface $input, OutputInterface $output)
    {
        $this->getLogger()->info('Shutting down gracefully...');
        // Close DB connections, release locks, etc.
    }
    
  2. Environment Awareness Use APP_ENV to disable daemons in dev:

    if ('dev' === $this->getContainer()->getParameter('kernel.environment')) {
        throw new \RuntimeException('Daemons disabled in dev environment.');
    }
    
  3. Resource Limits Daemons may hit memory limits. Use set_time_limit() or ini_set('memory_limit', '-1') cautiously.

  4. Testing Mock DaemonCommand in tests by extending it and overriding isTerminated():

    $command = $this->getMockBuilder(MyDaemonCommand::class)
        ->onlyMethods(['isTerminated'])
        ->getMock();
    $command->method('isTerminated')->willReturn(true);
    
  5. Extending Functionality

    • Custom Signals: Extend System_Daemon behavior by overriding DaemonCommand::setupSignals().
    • PID File: Use $this->getPidFile() to manage PID files:
      $pidFile = $this->getPidFile();
      if (file_exists($pidFile)) {
          $output->writeln('Daemon already running!');
          return 1;
      }
      
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.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
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
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony