Weave 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 Workerman Bundle Laravel Package

tourze/symfony-workerman-bundle

A Symfony bundle that integrates Workerman into Symfony applications, helping you run and manage persistent, event-driven Workerman workers and servers alongside your existing Symfony services, configuration, and console commands with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

The first thing to establish: despite showing up in a Laravel-oriented review queue, tourze/symfony-workerman-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config/workerman.php, and no facade. Treat it as a Symfony building block that you either (a) run inside a Symfony app alongside your Laravel service, or (b) mine for its wiring ideas and use workerman/workerman directly in Laravel.

Minimal steps in a Symfony host:

  1. composer require tourze/symfony-workerman-bundle:0.0.1 — pin the exact version. At 0.0.1 there is no BC promise and the changelog is a single auto-generated link.
  2. Register the bundle in config/bundles.php (Tourze\SymfonyWorkermanBundle\SymfonyWorkermanBundle::class => ['all' => true]). Flex auto-registration only happens if a recipe exists; assume it does not and register manually.
  3. Read DependencyInjection/Configuration.php before writing any config. In a 0.0.1 bundle this file is the only reliable documentation of what the config tree actually accepts — node names, defaults, and required keys.
  4. Read DependencyInjection/SymfonyWorkermanBundleExtension.php next, to see which services are registered unconditionally vs. behind a config flag, and what tags it looks for.
  5. Run bin/console list and grep for workerman to find the entry-point command. That command is your first use case: start a single long-running worker in the foreground, confirm it boots and binds a port, then build from there.

First real use case: a long-lived TCP/HTTP/WebSocket listener where you want Symfony's container to supply the handlers (repositories, loggers, HTTP clients) instead of hand-rolling new calls inside a Worker::onMessage closure.

For Laravel specifically: a Laravel-flavoured equivalent is a custom Artisan command wrapping Worker::runAll(), or Octane/RoadRunner if you only need HTTP. Do not expect Octane-style request sandboxing from this bundle.

Implementation Patterns

Worker-per-command. The idiomatic shape is one console command (or one configured worker entry) per logical server. Keep the Worker construction declarative and the behaviour in injected services — the bundle exists to let the container own those services.

Handlers as tagged services. The leverage you get from a bundle over raw Workerman is DI. Look for a tag (e.g. a worker/event tag) in the extension and register your onMessage / onConnect / onWorkerStart handlers as services with that tag. That keeps handlers unit-testable and injectable, and lets you swap implementations per environment.

Bootstrap-once, reset-per-request. The container is compiled once at boot and then lives for hours. Anything request-scoped must be reset. Wire Symfony's kernel.reset / services_resetter into your message loop, and explicitly clear accumulated state (Doctrine EntityManager::clear(), Monolog buffers, in-memory caches) on an interval or per message. This is the single most important pattern for a long-running worker and it is not something a 0.0.1 bundle will do for you.

Config-driven worker definitions. Put worker counts, listen addresses, and process settings in config/packages/*.yaml under the bundle's root key so dev/staging/prod differ without code edits. Read the config tree first — unknown keys are usually a hard failure, not a warning.

Integration with Symfony Messenger. The natural pairing: Workerman holds the socket and pushes payloads onto a Messenger transport (Redis/AMQP), and messenger:consume workers do the heavy lifting. This keeps your long-running socket process thin and lets Messenger handle retries and failure transport. Avoid doing blocking DB/HTTP work directly in onMessage — one slow handler stalls every connection on that worker.

Supervisor/systemd over -d. Do not daemonize inside the process. Run foreground under systemd or Supervisor with Restart=always, so restarts, logs, and exit codes are managed outside PHP. In containers, foreground is the only sane mode.

Deploy workflow. Because PHP code is loaded once, deploys need an explicit reload/restart step (reload for graceful, restart for hard). Put that in your deploy script next to cache:clear — deploying without it silently keeps serving old code.

Gotchas and Tips

  • 0.0.1 means "no contract". No docs, no changelog content, no deprecation policy. Pin 0.0.1 exactly, read the source, and expect to re-read it on every bump. Budget for a fork-and-maintain scenario.
  • Memory growth is the default failure mode. Watch RSS over hours, not minutes. opcache.validate_timestamps=0 in production is faster but means code changes require a full restart, not a reload.
  • Doctrine will bite you. A single failed flush closes the EntityManager permanently for that process. Either reset it per message or catch and re-open it. Same story for any service that latches error state.
  • Xdebug will hang your worker or make it unusably slow. Disable it for the server process; use logging, not step-debugging, in the loop.
  • echo is a debugging trap. Under Supervisor/systemd stdout goes to the journal, but buffering and worker interleaving make output unreliable in production. Use the injected LoggerInterface.
  • Port/bind conflicts. EADDRINUSE after a crash usually means an orphaned child process — check ps for stale workers before restarting. Multiple workers binding the same port needs reusePort on Linux; Windows has no fork, so worker counts > 1 won't behave as expected.
  • Graceful reload semantics. reload waits for in-flight connections, so a stuck handler blocks the reload indefinitely. Know your timeout, and keep a restart path available.
  • Container staleness in dev. Long-running processes never see cache:clear effects. Restart the worker after DI/config changes, or you will debug a phantom.
  • Extension points to prefer: the DI extension's tag names, the config tree (for anything environment-dependent), and overriding individual services in config/services.yaml. Avoid subclassing bundle internals — at 0.0.1 those classes are the most likely to move.
  • Verify before adopting: confirm the bundle actually manages the worker lifecycle (reload/stop commands, signal handling) rather than only registering a Worker instance. If it is thin, you are paying bundle-shaped coupling for something a 60-line Artisan/console command would do more transparently.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings