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

Messenger Worker Registry Laravel Package

roman-1983/messenger-worker-registry

A Laravel package that provides a registry for messenger workers, making it easy to register, discover, and manage worker definitions in your application. Ideal for organizing background message consumers and keeping worker configuration consistent.

View on GitHub
Deep Wiki
Context7

Getting Started

This package lives in Symfony Messenger territory, not Laravel queues. Before writing any code, confirm you actually run Messenger workers — a Laravel app using Redis/SQS/Horizon has no Symfony worker lifecycle to hook into, and this package will do nothing for you. It fits only if you run standalone messenger:consume processes (hybrid Symfony/Laravel estate, sidecar consumers, or a custom bridge).

Minimal onboarding:

  1. Read the source first. At 2 stars and 0 dependents this is unproven code. src/ is small enough to audit in an hour. Answer three questions before proceeding: What storage backend does the registry use (Redis, Doctrine, cache)? Does it write heartbeats on a timer, on WorkerRunningEvent, or only on start? Does it clean up stale entries?
  2. Check composer.json constraints. Look at the pinned symfony/messenger and PHP versions — small packages often lock old versions that will fight your framework upgrade.
  3. Require it: composer require roman-1983/messenger-worker-registry.
  4. Register the bundle/service. If it's a Symfony bundle, add it to config/bundles.php. If not, import its service definition manually — check Configuration.php for the config key (likely under messenger_worker_registry:).
  5. Wire the storage backend to your existing Redis/cache connection. Do not let it spin up a second connection; you want one thing to monitor, not two.
  6. Smoke test: start one messenger:consume worker, then query the registry (via injected service or a shipped console command) and confirm the worker appears with name, PID, host, and status. If the worker never registers, nothing downstream matters — debug that first.

Implementation Patterns

Health endpoint pattern (the primary use case). Expose the registry through a small controller or Laravel route: pull active workers, compare last_seen against now() - heartbeat_interval, and return a status summary. Let your external monitoring (Uptime, Datadog synthetic, a cron) poll it. This is the whole value proposition: one endpoint answering "which consumers are alive?" without scraping every pod.

Route::get('/health/workers', function (WorkerRegistry $registry) {
    $workers = $registry->all();
    $stale = array_filter($workers, fn ($w) => $w->lastSeen < now()->subSeconds(90));
    return response()->json([
        'total' => count($workers),
        'stale' => count($stale),
        'workers' => $workers,
    ]);
});

Scale-decision pattern. Before scaling a consumer deployment up, query the registry to see how many workers are actually alive per queue. This catches the classic "scaled up, but old pods are still registered as zombies" case during rolling restarts and blue/green deploys.

Graceful shutdown coordination. Register on worker start, deregister on WorkerRunningEvent when isWorkerIdle() fires, or in your SIGTERM handler. Wire this into supervisor/systemd stop logic so the registry reflects reality rather than accumulating ghosts. For canary verification after deploy, diff the registry between before and after — you should see exactly the workers you intended to replace.

Multi-queue keying. If you run workers per transport (--queues=high,low), key registry entries by queue name so dashboards can show worker counts per queue alongside depth. This is what makes per-queue capacity planning possible.

Wrap it behind your own interface. Define WorkerRegistry with methods like activeCount(string $queue): int, all(): array, isAlive(string $workerId): bool. Even if you only use one implementation, the wrapper is what lets you swap the package out later without a codebase-wide refactor — and given the maturity signals, you probably will.

Fail-open, always. Registry writes must never block job processing. If the backend is down, the worker should log and continue consuming; only the dashboard goes stale.

Gotchas and Tips

  • Stale entries are the #1 failure mode. Most naive registries register on start but never expire dead workers — a crashed consumer lingers forever and skews every scaling decision. Verify the package has a TTL or heartbeat sweep; if not, add your own reaper on last_seen and run it from a scheduled command.
  • Storage choice dictates reliability. Redis-backed is only as reliable as Redis during a restart storm. In-memory or file-based won't survive across containers, so it's useless in Kubernetes. Confirm which you're getting before trusting the counts.
  • Config quirks. If it's a bundle, keys live under a namespaced config tree — check Configuration.php. Services are usually autoconfigured; if not, you must tag the worker event subscriber manually or it silently never runs, and you'll see an empty registry with zero errors.
  • Debug by inspecting storage directly. Before trusting the package's reader, hit Redis KEYS messenger:* (or the equivalent Doctrine table) and look at raw values. If writes and reads disagree, you have a serialization or connection mismatch, not a code bug.
  • Heartbeat interval vs TTL. TTL should be ~3× the heartbeat interval to absorb one dropped beat without flapping. Too tight and every restart storm fires false alerts; too loose and zombies persist. Start at 30s heartbeat / 90s TTL and tune against observed jitter.
  • Multi-host coordination. Heartbeats from multiple hosts can race if the backend doesn't support atomic upserts. Confirm idempotent registration before scaling to many workers, and load-test the registry path under high worker churn — a hot-path write per heartbeat is a real bottleneck with hundreds of consumers.
  • Extension points. Look for a WorkerRegistryInterface you can implement to swap Redis for Doctrine or decorate with a heartbeat wrapper. If none exists, that's a fork candidate — the small surface area here makes forking cheap.
  • Maturity caveat. 2 stars, 0 dependents, no CVE history, no ecosystem. Budget to vendor the code, pin the version, and add CI coverage against the PHP/Symfony/Laravel versions you actually run. Treat this as a reference implementation to copy and harden, not a load-bearing dependency.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource