- What is m6web/daemon-bundle and what problem does it solve?
- It is a Symfony bundle that provides an abstract daemon command base class on top of the Console component, handling startup, timed execution through a ReactPHP event loop, and shutdown. You extend the class and implement your recurring business logic while the bundle manages the process lifecycle, signal handling, memory-limit checks, and logging hooks. It targets workers, queue consumers, and background jobs that must keep running rather than execute once and exit.
- Can I use m6web/daemon-bundle in a Laravel application?
- Not directly. The package is a Symfony bundle with a Bundle subclass, registerBundles() wiring, and a container extension with a config tree, none of which exist in Laravel, so DaemonBundle::boot() stays inert there. Only the abstract daemon command concept transfers, roughly thirty to forty percent of the code, and it requires a fork-and-adapt approach: vendor the base class into app/Console/Daemons/ or build an internal package with a service provider plus Artisan::starting().
- How do I install and register m6web/daemon-bundle?
- Install it with Composer via composer require m6web/daemon-bundle, noting the repository has moved to BedrockStreaming/DaemonBundle, then register the bundle in your Symfony kernel and configure it through the bundle extension. It hard-requires the pcntl and ext-posix extensions, so confirm both are compiled into your PHP CLI before any design work. In Laravel there is no bundle registration step at all, so you would be copying classes rather than wiring the bundle.
- How do I write a daemon command with m6web/daemon-bundle?
- You extend the provided daemon command base class and implement your loop body, while the base class drives startup, periodic execution on a ReactPHP timer, and shutdown. In v9.0.0 signal handling comes from a ConsoleCommandListener registered on the Symfony Console event dispatcher rather than an overridden handleSignal() method, so keep business logic out of lifecycle methods. A practical pattern is to delegate the recurring work to a service class so the loop body stays thin and testable.
- Which Symfony and Laravel versions are compatible with m6web/daemon-bundle v9.0.0?
- Version 9.0.0 is explicitly a Symfony 7.3 compatibility release, so read the real symfony/console and symfony/http-kernel constraints in composer.json instead of assuming. A constraint like ^7.3 will not install on a Laravel 11 app locked to Symfony 7.0 through 7.2, while Laravel 11 and 12 pin Symfony Console 6.4 or 7.x depending on the release. Because the package tracks upstream Symfony rather than Laravel, treat every Symfony bump as an audit point for your fork.
- Does m6web/daemon-bundle run on Windows or in minimal PHP CLI containers?
- No. pcntl and ext-posix remain hard requirements, which rules out Windows and many minimal php:cli images built without those extensions. Verify the extension set across your entire fleet, including CI runners and container base images, before committing to a design. Without pcntl the graceful shutdown and timer behavior simply do not apply.
- How does m6web/daemon-bundle v9.0.0 handle SIGTERM and SIGINT for graceful shutdown?
- Signal handling moved out of an overridden handleSignal() method and into a ConsoleCommandListener registered against the Symfony Console event dispatcher. That is more portable in principle, but it makes signal handling a runtime wiring concern: if the listener is registered on the wrong dispatcher or registered twice, SIGTERM handling fails open and the process dies mid-iteration instead of draining. Audit any vendored copy that still overrides handleSignal, because Symfony 7.3 adds its own handleSignal on the command layer and a stale override can trigger a signature-compatibility fatal.
- Is m6web/daemon-bundle a good alternative to Laravel Horizon or queue:work?
- For queue consumption, no. Laravel already ships daemon-mode primitives in queue:work, Horizon, schedule:run under cron, and Octane, and introducing a second, non-idiomatic concurrency model carries a maintenance cost this release does nothing to reduce. Consider borrowing the bundle's lifecycle ideas only for workloads those tools handle poorly, such as polling an external API or holding a long-lived socket open. If your workload is queue jobs, use Horizon.
- Does the bundle handle memory limits, restarts, and logging for long-running processes?
- It provides memory-limit checks, restart safeguards, and logging hooks so operators can see when a daemon restarts or exits, which is more than a bare while loop gives you. The remaining hazards are still yours to own: Eloquent connection state, DB::reconnect() after failures, scoped bindings that never reset, and unbounded memory growth from models and query logs. There is no built-in equivalent of the max-time and memory flags on queue:work, so plan your own guardrails.
- How should I test a daemon command built with m6web/daemon-bundle?
- Keep the recurring business logic in a separate service and unit test that directly, then exercise the loop body in isolation with a fake timer or a single controlled iteration. Also assert that signal handling is registered against the correct event dispatcher, because a misregistered listener fails silently until a deploy sends SIGTERM. Full end-to-end daemon tests are slow and depend on pcntl, so cover lifecycle wiring with one focused integration test and leave the rest to service-level tests.