PHPackages                             roman-1983/messenger-worker-registry - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. roman-1983/messenger-worker-registry

ActiveSymfony-bundle[Logging &amp; Monitoring](/categories/logging)

roman-1983/messenger-worker-registry
====================================

Worker registry for Symfony Messenger — track running workers, transports, and message stats via console

v1.3.0(1mo ago)2714MITPHPPHP &gt;=8.2CI passing

Since Mar 3Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/ShopWatch-io/messenger-worker-registry)[ Packagist](https://packagist.org/packages/roman-1983/messenger-worker-registry)[ Docs](https://github.com/ShopWatch-io/messenger-worker-registry)[ RSS](/packages/roman-1983-messenger-worker-registry/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (27)Versions (8)Used By (0)

Messenger Worker Registry
=========================

[](#messenger-worker-registry)

The Messenger Worker Registry component provides real-time visibility into your Symfony Messenger workers. Track running workers, their transports, message throughput, failure rates, and per-message-type performance — all via a simple console command.

Features
--------

[](#features)

- **Zero configuration** — install the bundle and it just works
- **Automatic registration** — workers register themselves on startup via event listeners
- **Worker status** — see at a glance which workers are `running`, `stopped`, or `dead`
- **Hostname tracking** — identify which host each worker is running on
- **Heartbeat with TTL** — crashed workers show as "dead" before expiring from the registry
- **Configurable TTL** — adjust the TTL to match your environment
- **Message counters** — track handled and failed messages per worker
- **Per-message-type stats** — see count, failure rate, and average processing time per message class
- **Console command** — `messenger:worker:list` with table and JSON output
- **Web Debug Toolbar** — see worker count and status at a glance in the Symfony profiler
- **Configurable cache pool** — use any PSR-6 cache pool instead of the default `cache.app`
- **No external dependencies** — uses Symfony's built-in PSR-6 cache (filesystem, Redis, APCu — whatever you have configured)

Requirements
------------

[](#requirements)

- PHP 8.2+
- Symfony 7.0+ or 8.0+

Installation
------------

[](#installation)

```
composer require roman-1983/messenger-worker-registry
```

If you're not using Symfony Flex, register the bundle manually:

```
// config/bundles.php
return [
    // ...
    ShopWatch\MessengerWorkerRegistry\MessengerWorkerRegistryBundle::class => ['all' => true],
];
```

That's it. No configuration needed — the defaults work out of the box.

Usage
-----

[](#usage)

### List Running Workers

[](#list-running-workers)

```
bin/console messenger:worker:list
```

[![messenger:worker:list](docs/worker-list.png)](docs/worker-list.png)

### Worker Status

[](#worker-status)

Each worker has one of three statuses:

StatusMeaning`running`Worker is active, heartbeat received within TTL`stopped`Worker shut down gracefully via `WorkerStoppedEvent``dead`Worker crashed — no heartbeat received for longer than TTLStopped workers remain visible for 1x TTL after shutdown. Dead workers remain visible for 2x TTL after their last heartbeat, then expire from the cache automatically.

### Detailed View with Per-Message Stats

[](#detailed-view-with-per-message-stats)

```
bin/console messenger:worker:list --detail
```

[![messenger:worker:list --detail](docs/worker-detail.png)](docs/worker-detail.png)

### JSON Output

[](#json-output)

```
bin/console messenger:worker:list --format=json
bin/console messenger:worker:list --format=json --detail
```

Returns a JSON array for programmatic consumption:

```
[
  {
    "id": "a3f21b8e",
    "status": "running",
    "hostname": "web-01",
    "transports": ["scheduler_uptime", "high", "medium"],
    "started_at": "2026-03-03T14:22:10+00:00",
    "last_active_at": "2026-03-03T14:24:55+00:00",
    "messages_handled": 142,
    "messages_failed": 0,
    "message_stats": {
      "CheckUptimeMessage": {
        "count": 120,
        "failed": 0,
        "avg_ms": 198.3,
        "total_ms": 23796.0
      }
    }
  }
]
```

The `message_stats` key is only included when using `--detail`.

Web Debug Toolbar
-----------------

[](#web-debug-toolbar)

When `symfony/web-profiler-bundle` is installed, the bundle automatically adds a toolbar item showing the number of running workers. The toolbar icon turns **red**when dead workers are detected, and **yellow** when no workers are running.

[![Web Debug Toolbar](docs/toolbar.png)](docs/toolbar.png)

Click the toolbar item to open the full profiler panel with:

- Summary metrics (running / stopped / dead counts, handled / failed totals, TTL)
- Worker table with status, hostname, transports, relative timestamps, and message counters
- Per-message-type breakdown with count, failure rate, total and average processing time

No extra configuration is needed — the data collector is registered automatically.

[![Profiler Panel](docs/profiler-panel.png)](docs/profiler-panel.png)

How It Works
------------

[](#how-it-works)

The bundle listens to Symfony Messenger's built-in worker events:

EventAction`WorkerStartedEvent`Registers the worker with a generated ID, hostname, and transport list`WorkerRunningEvent`Sends a heartbeat every 30s to extend the cache TTL`WorkerStoppedEvent`Marks the worker as "stopped" (stays visible for 1x TTL)`WorkerMessageReceivedEvent`Starts a timer for processing duration`WorkerMessageHandledEvent`Increments handled counter, records per-type stats`WorkerMessageFailedEvent`Increments failed counter, records per-type stats### TTL and Worker Lifecycle

[](#ttl-and-worker-lifecycle)

Each worker entry is stored with a cache TTL of **2x the configured TTL**(default: 240 seconds). The heartbeat (fired every 30 seconds) resets this TTL on each cycle.

- **Running**: Heartbeat keeps the entry alive. Status is "running" as long as `lastActiveAt` is within 1x TTL.
- **Crashed**: If a worker crashes without triggering `WorkerStoppedEvent`, its `lastActiveAt` goes stale. After 1x TTL it shows as "dead". After 2x TTL the cache entry expires automatically.
- **Graceful stop**: `WorkerStoppedEvent` sets `stoppedAt` and saves the entry with 1x TTL. It shows as "stopped" until it expires.

### Storage

[](#storage)

The bundle uses Symfony's `cache.app` pool by default. This means it works out of the box with whatever cache adapter you have configured (filesystem, Redis, Memcached, APCu). For multi-server setups, make sure your cache adapter is shared (e.g., Redis).

> **Docker / multi-container note:** If your web server and workers run in separate containers with the default filesystem cache adapter, they each have an isolated filesystem. Workers will register themselves, but the web container won't see them. To fix this, either mount a **shared volume** on the cache directory (e.g., `/app/var/share`) across all containers, or switch to a shared cache adapter like Redis.

Configuration
-------------

[](#configuration)

**Zero configuration** — the bundle works out of the box. It uses Symfony's `cache.app` pool (typically filesystem) and a default TTL of 120 seconds. No Redis, no database, no external services required.

> **Important:** Workers and your web application **must share the same cache**. Workers write their status to the cache, and the web app (console command, profiler panel) reads from it. If they use separate cache pools or isolated filesystems, the registry will appear empty.

You can optionally customize the TTL, cache pool, and lock factory:

```
# config/packages/messenger_worker_registry.yaml
messenger_worker_registry:
    ttl: 120          # seconds (default: 120, minimum: 10)
    cache: cache.app  # cache pool service ID (default: cache.app)
    lock: ~           # lock factory service ID (default: built-in flock factory)
```

Index writes are serialized with a lock so that workers starting concurrently (e.g. all queues on `docker compose up`) cannot clobber each other's entries. By default a built-in flock-based factory under `%kernel.cache_dir%` is used, so the lock is shared exactly where the cache is. For a multi-host setup, point `lock` at a `Symfony\Component\Lock\LockFactory` backed by a shared store (Redis, PDO, …) the same way you would share the cache.

If you need a dedicated cache pool (e.g., to use a different adapter or separate the worker data from your application cache), define one and reference it:

```
# config/packages/cache.yaml
framework:
    cache:
        pools:
            cache.worker_registry:
                adapter: cache.adapter.filesystem

# config/packages/messenger_worker_registry.yaml
messenger_worker_registry:
    cache: cache.worker_registry
```

Testing
-------

[](#testing)

```
composer install
vendor/bin/phpunit
```

Resources
---------

[](#resources)

- [Contributing](CONTRIBUTING.md)
- [Report issues](https://github.com/roman-1983/messenger-worker-registry/issues) and [send Pull Requests](https://github.com/roman-1983/messenger-worker-registry/pulls) please.

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance93

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~13 days

Recently: every ~20 days

Total

7

Last Release

34d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7a38120affa7e137b517d7829a77330ffe2c091c78a53eaf258c5ebc0c1f7f6a?d=identicon)[roman-1983](/maintainers/roman-1983)

---

Top Contributors

[![roman-1983](https://avatars.githubusercontent.com/u/3573021?v=4)](https://github.com/roman-1983 "roman-1983 (14 commits)")

---

Tags

composer-packagesymfonysymfonymonitoringworkerMessengerregistry

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/roman-1983-messenger-worker-registry/health.svg)

```
[![Health](https://phpackages.com/badges/roman-1983-messenger-worker-registry/health.svg)](https://phpackages.com/packages/roman-1983-messenger-worker-registry)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.5M376](/packages/easycorp-easyadmin-bundle)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M196](/packages/sulu-sulu)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.4M519](/packages/shopware-core)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

9317.2k55](/packages/open-dxp-opendxp)[shopware/storefront

Storefront for Shopware

674.4M209](/packages/shopware-storefront)[chameleon-system/chameleon-base

The Chameleon System core.

1027.9k4](/packages/chameleon-system-chameleon-base)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
