Operations

# Dashboard

Mount the engine to see queues, jobs, failures, and dead letters — auto-refreshing over Turbo Frames.

## Mount it

```ruby
mount Pgbus::Engine => "/pgbus"
```

The dashboard is a mountable Rails engine. Every table auto-refreshes over Turbo Frames — no WebSocket, no Action Cable. Destructive actions use styled confirmation dialogs and flash as toast notifications.

## The panels

| Panel | Shows |
| --- | --- |
| Overview | Queue depths, enqueued count, active processes, failures, throughput rate. |
| Queues | Per-queue metrics with purge / pause / resume / delete. |
| Jobs | Enqueued and failed jobs, with retry / discard. |
| Dead letter | DLQ messages with retry / discard and bulk actions. |
| Processes | Active workers, dispatcher, consumers with heartbeat status **and per-worker throughput** (e.g. `12.4/s processed · 0.2/s failed`). |
| Events | Registered subscribers and processed events. |
| Outbox | Transactional outbox entries pending publication. |
| Locks | Active uniqueness locks — state, owner PID@host, age. |
| Insights | Throughput chart, status distribution, slowest job classes. |

> **Note:** The Insights page reads `pgbus_job_stats` — add it with `rails generate pgbus:add_job_stats`. Stats are buffered and bulk-inserted; if the migration hasn't run, recording is silently skipped.

Each worker snapshots its live in-process rate counter (dequeued / processed / failed) into its heartbeat metadata on every beat, so the Processes panel shows a cluster-wide, near-real-time throughput view with no extra query — `Web::DataSource` just passes the existing heartbeat metadata through. Zero rates are omitted from the rendered string. Non-worker processes (dispatcher, scheduler, consumers) carry no rate data and render only their static boot metadata, unchanged.

## Protect it in production

The dashboard has no auth of its own.

Guard the mounted engine with a `web_auth` lambda:

```ruby
Pgbus.configure do |config|
  config.web_auth = ->(request) { request.env["warden"]&.user&.admin? }
end
```

Or inherit from your own authenticated controller — then its `before_action` filters and helpers apply automatically, with no monkey-patching:

```ruby
Pgbus.configure do |config|
  config.base_controller_class = "Admin::BaseController"
  config.return_to_app_url     = "/admin" # adds a "back to app" button
end
```

> **Warning:** The dashboard exposes queue contents and destructive actions (purge, delete, discard). Never mount it unauthenticated in production.