Skip to content

fix(metrics): vt-aware oldest_claimable_age_sec — one delayed job no longer reads as a degraded queue - #390

Merged
mhenrixon merged 3 commits into
mainfrom
issue-389-claimable-age-metric
Aug 4, 2026
Merged

fix(metrics): vt-aware oldest_claimable_age_sec — one delayed job no longer reads as a degraded queue#390
mhenrixon merged 3 commits into
mainfrom
issue-389-claimable-age-metric

Conversation

@mhenrixon

@mhenrixon mhenrixon commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

pgmq's oldest_msg_age_sec is computed from enqueued_at and ignores vt — but a job enqueued with wait: or parked on a retry backoff lives in the queue table with a future vt (that is the delayed-delivery mechanism). One parked message therefore made the age metric grow at wall-clock rate for hours on an otherwise drained queue, and any latency alert thresholding on it fired continuously.

This adds a vt-aware oldest_claimable_age_secnow() - min(vt) over rows with vt <= now(), i.e. the age of the oldest message actually eligible for pickup — to every metrics surface:

  • Web::DataSource#batched_queue_metrics / #queue_metrics_via_sql (lib/pgbus/web/data_source.rb) — feeds dashboard, JSON API, and the MCP pgbus_queues tool
  • New Prometheus gauge pgbus_queue_oldest_claimable_age_seconds (lib/pgbus/web/metrics_serializer.rb), nil-skipped
  • AppSignal probe (lib/pgbus/integrations/appsignal/probe.rb): ⚠️ pgbus_queue_latency now derives from the claimable age and always emits ((claimable || 0) * 1000, 0 = no claimable backlog) — existing latency alerts stop false-firing with no dashboard changes. The raw pgbus_queue_oldest_message_age_seconds gauge keeps enqueue-time semantics; a new pgbus_queue_oldest_claimable_age_seconds gauge is added, nil-skipped
  • Pgbus::Client#oldest_claimable_ages(queue_name = nil) (lib/pgbus/client.rb) — raw-SQL reader (pgmq's metrics_result type is frozen upstream, so the SQL function can't grow the field), single-queue age or all-queues hash
  • CLI pgbus queues gains a CLAIMABLE (s) column
  • Dashboard queue tables split depth into Parked (depth − visible) and show the claimable age instead of the raw age; queue detail header shows both; all 12 locales updated

Semantics: an immediately-enqueued message contributes from enqueue time (matches the old number on a plain backlog); a scheduled/backoff-parked message contributes nothing until due — then grows at wall-clock rate, which is exactly the starvation signal the alert wants; an in-flight message (vt pushed forward) is excluded; nil means "no claimable backlog" even when the table is non-empty.

Closes #389

Test plan

  • Unit: DataSource SQL selects min(vt) scoped to vt <= NOW(); a parked-only queue maps oldest_claimable_age_sec to nil while oldest_msg_age_sec keeps counting (the incident shape from Queue-age metrics count vt-parked (scheduled/retrying) messages, so one delayed job reads as a degraded queue #389)
  • Unit: Prometheus gauge emitted per queue, skipped when nil
  • Unit: AppSignal queue_latency = claimable × 1000; 0 for parked-only and empty queues; raw gauge unchanged; claimable gauge nil-skipped
  • Unit: Client#oldest_claimable_ages — prefixed single-queue read and all-queues hash via with_raw_connection
  • Unit: CLI CLAIMABLE column, dash for parked-only
  • Integration (real PG + PGMQ): message sent with delay: 3600 → claimable nil while raw age counts it; immediate message → age ≥ 0 on both paths; message read with vt: 60 (in-flight) → claimable nil
  • Full suite: 4226 examples, only the 2 known pre-existing i18n baseline failures (vendored apexcharts scan error); rubocop, herb lint, docs lint all clean

Deviations & judgment calls

  • Deviation: The plan pointed the docs update at docs/app/views/docs/pages/observability.rb's "gauge list" — that page only documents the event-driven metrics backend; the dashboard-scrape gauge table actually lives in README.md ("Prometheus metrics"). Added the new gauge row to the README table and expanded the AppSignal section wording in the docs page instead.
  • Deviation: Removed the now-unused queues_table.headers.oldest / queues_list.headers.oldest keys from all 12 locales — the plan only said "add keys", but spec/i18n_spec.rb runs i18n-tasks' unused-keys check, which would fail once the views stopped referencing them.
  • Judgment call: In queue_metrics_via_sql the claimable age uses an aggregate FILTER (WHERE vt <= NOW()) inside the existing single-pass CTE, while batched_queue_metrics uses a scalar subselect — each matches the surrounding query's existing style; both produce identical results.
  • Judgment call: Locale translations for "Oldest claimable"/"Parked" in the 11 non-English languages were written to match each file's existing terminology (e.g. de "Älteste verfügbar (s)"/"Geparkt", fr "Différés"); a native review pass wouldn't hurt, as with the existing translations.
  • Judgment call: Client#oldest_claimable_ages runs one query per queue on the all-queues path (same shape as pgmq's own metrics_all loop) rather than one dynamic-SQL statement — table names are per-queue identifiers and the only caller is the CLI.
  • Discovery: pgmq-ruby's metrics struct returns queue_length as a string on the integration path; the integration spec compares via .to_i.
  • Judgment call: AppSignal queue_latency always emits (0 when nothing is claimable) so alert series show "healthy" rather than no-data; the raw and claimable age gauges stay nil-skipped, mirroring the existing idiom.

Summary by CodeRabbit

  • New Features
    • Added claimable-message age metrics across dashboards, queue details, CLI output, and client APIs.
    • Added the Prometheus gauge pgbus_queue_oldest_claimable_age_seconds.
    • Queue views now show parked message counts separately from claimable backlog.
  • Bug Fixes
    • Queue latency now excludes scheduled, retrying, and in-flight messages until eligible for processing.
    • Monitoring reports zero or no value when no messages are currently claimable.
  • Documentation
    • Updated metrics and observability documentation, including localized queue labels.

…longer reads as a degraded queue

## Summary
pgmq's oldest_msg_age_sec ignores vt, so a scheduled or backoff-parked
message made age-based latency alerts fire for hours on healthy queues.
Every metrics surface now exposes oldest_claimable_age_sec (now() - min(vt)
over rows with vt <= now()): DataSource (dashboard/API/MCP), Prometheus
gauge, AppSignal gauge, Client#oldest_claimable_ages, CLI CLAIMABLE column.
AppSignal queue_latency now derives from the claimable age (always emitted,
0 = no claimable backlog). Dashboard queue tables split depth into
claimable vs parked and show the claimable age.

## Test Coverage
- data_source specs: SQL selects min(vt) scoped to claimable rows; parked-only queue maps to nil
- metrics_serializer spec: new gauge emitted, nil-skipped
- probe spec: queue_latency from claimable age, 0 when parked-only; raw gauge unchanged
- client spec: prefixed single-queue read + all-queues hash via raw connection
- cli spec: CLAIMABLE column, dash for parked-only
- integration spec (real PG): delayed message -> nil claimable while raw age counts it; in-flight excluded

## Verification
- [x] bundle exec rubocop passes
- [x] bundle exec rspec passes (only the 2 known pre-existing i18n baseline failures)
- [x] bun run lint:herb passes
- [x] docs rake lint passes

Refs #389
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Queue metrics now distinguish claimable backlog from scheduled, retrying, and in-flight messages. Claimable age appears in APIs, Prometheus, AppSignal, CLI output, dashboards, documentation, and tests.

Changes

Claimable Queue Metrics

Layer / File(s) Summary
Claimable age calculation
lib/pgbus/client.rb, lib/pgbus/web/data_source.rb, spec/integration/*, spec/pgbus/client_spec.rb, spec/pgbus/web/*
The client and web data sources calculate age from messages where vt <= NOW(). Tests cover delayed, claimable, and in-flight messages.
Observability and CLI exposure
lib/pgbus/integrations/appsignal/probe.rb, lib/pgbus/web/metrics_serializer.rb, lib/pgbus/cli.rb, lib/pgbus/mcp/tools/queues_tool.rb, README.md, docs/..., CHANGELOG.md, spec/pgbus/..., spec/support/..., spec/dummy/...
AppSignal latency uses claimable age. Prometheus emits a claimable-age gauge. The CLI displays a CLAIMABLE column. Documentation and fixtures describe the metric.
Dashboard queue state display
app/views/pgbus/..., config/locales/*.yml
Queue views display parked depth and oldest claimable age. Localized labels and empty-state column spans are updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant QueueTables
  participant Client
  participant WebDataSource
  participant AppSignalProbe
  participant MetricsSerializer
  QueueTables-->>Client: Claimable age or nil
  QueueTables-->>WebDataSource: Claimable queue metric
  WebDataSource->>MetricsSerializer: Serialize claimable age
  WebDataSource->>AppSignalProbe: Provide claimable age
  AppSignalProbe-->>AppSignalProbe: Set latency to claimable age
Loading

Possibly related PRs

  • mhenrixon/pgbus#148: Both changes update Pgbus::Integrations::Appsignal::Probe queue latency behavior.

Suggested labels: bug, testing, documentation

Poem

A rabbit checks the queue at dawn,
Parked messages wait until due.
Claimable age reports ready work,
AppSignal measures only what is true.
Prometheus and dashboards follow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding vt-aware oldest_claimable_age_sec metric to prevent delayed jobs from appearing as degraded queues.
Linked Issues check ✅ Passed The PR fully implements issue #389: exposes oldest_claimable_age_sec metric calculated from vt <= now(), integrates it into dashboards, APIs, Prometheus, AppSignal, CLI, and client library with comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes directly support the vt-aware claimable-age metric: data sources, serializers, views, localizations, documentation, client methods, and tests are all within scope.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-389-claimable-age-metric

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/views/pgbus/dashboard/_queues_table.html.erb (1)

1-1: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Move the "parked" calculation into the data layer instead of duplicating it in three views.

All three views independently compute parked depth as queue_length - queue_visible_length. Add a parked_length field to the metrics hashes returned by batched_queue_metrics and queue_metrics_via_sql in lib/pgbus/web/data_source.rb, then reference that field from each view. This removes the duplicated arithmetic and keeps the "parked" definition in one place if it needs to change later (for example, to guard against unexpected negative values).

  • app/views/pgbus/dashboard/_queues_table.html.erb#L29-30: replace q[:queue_length] - q[:queue_visible_length] with q[:parked_length] once the data source exposes it.
  • app/views/pgbus/queues/_queues_list.html.erb#L28-29: replace q[:queue_length] - q[:queue_visible_length] with q[:parked_length].
  • app/views/pgbus/queues/show.html.erb#L16-17: replace @queue[:queue_length] - @Queue[:queue_visible_length] with @queue[:parked_length].
♻️ Proposed data-layer addition
           name: row["queue_name"],
           queue_length: row["queue_length"].to_i,
           queue_visible_length: row["queue_visible_length"].to_i,
+          parked_length: row["queue_length"].to_i - row["queue_visible_length"].to_i,
           oldest_msg_age_sec: row["oldest_msg_age_sec"]&.to_i,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/views/pgbus/dashboard/_queues_table.html.erb` at line 1, Centralize
parked-depth calculation in the data layer: update batched_queue_metrics and
queue_metrics_via_sql in DataSource to include a parked_length field in every
metrics hash, then update the queues table, queues list, and queue show views to
read q[:parked_length] or `@queue`[:parked_length] instead of subtracting
queue_visible_length from queue_length.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/pgbus/client.rb`:
- Around line 556-565: Update oldest_claimable_ages to invoke
with_raw_connection with synchronization enabled, ensuring the shared
PG::Connection path is protected while executing both the metadata query and
claimable_age_for calls. Preserve the existing queue-specific and all-queues
behavior.

In `@lib/pgbus/mcp/tools/queues_tool.rb`:
- Around line 17-20: Update the queue metric documentation around
oldest_claimable_age_sec to state that nil means no message is currently
eligible for pickup, including cases where messages are scheduled,
backoff-parked, or in flight with a future vt; do not describe nil as proof that
the queue is healthy.

In `@README.md`:
- Line 994: The documentation for the pgbus_queue_oldest_claimable_age_seconds
metric does not explain its absent-series behavior. Update the metric
description to clarify that when this gauge is absent (nil, not emitting a zero
sample), it indicates there is no claimable backlog. Include context that this
absence is distinct from the raw enqueue-age gauge, which may still report
parked messages waiting for their visibility timeout to elapse.

In `@spec/integration/claimable_age_metrics_spec.rb`:
- Around line 31-32: Update the assertion for oldest_claimable_ages to fetch the
queue using client.config.queue_name("claimable_test") instead of the hardcoded
"pgbus_int_claimable_test" key, preserving the existing age expectation.

In `@spec/pgbus/web/data_source_batched_metrics_spec.rb`:
- Around line 93-118: The batched metrics specs only assert SQL tokens and
mocked results, so they do not prove future visibility times are excluded.
Strengthen the coverage around queues_with_metrics and batched_queue_metrics by
adding a PostgreSQL-backed case with both due and future-vt rows, asserting the
claimable age excludes future rows and includes them once due; verify or extend
spec/integration/claimable_age_metrics_spec.rb for both timing states.
- Around line 127-135: The batched metrics fixture’s retry-parked scenario is
inconsistent because max_read_ct is zero. In the select_all stub within the
metrics spec, set max_read_ct to a positive read count so it represents a
previously claimed message, preserving the rest of the scenario.

---

Outside diff comments:
In `@app/views/pgbus/dashboard/_queues_table.html.erb`:
- Line 1: Centralize parked-depth calculation in the data layer: update
batched_queue_metrics and queue_metrics_via_sql in DataSource to include a
parked_length field in every metrics hash, then update the queues table, queues
list, and queue show views to read q[:parked_length] or `@queue`[:parked_length]
instead of subtracting queue_visible_length from queue_length.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 21ac42e2-bc83-4300-bf31-41751947a7d5

📥 Commits

Reviewing files that changed from the base of the PR and between 8a6c461 and 308862b.

📒 Files selected for processing (33)
  • CHANGELOG.md
  • README.md
  • app/views/pgbus/dashboard/_queues_table.html.erb
  • app/views/pgbus/queues/_queues_list.html.erb
  • app/views/pgbus/queues/show.html.erb
  • config/locales/da.yml
  • config/locales/de.yml
  • config/locales/en.yml
  • config/locales/es.yml
  • config/locales/fi.yml
  • config/locales/fr.yml
  • config/locales/it.yml
  • config/locales/ja.yml
  • config/locales/nb.yml
  • config/locales/nl.yml
  • config/locales/pt.yml
  • config/locales/sv.yml
  • docs/app/views/docs/pages/observability.rb
  • lib/pgbus/cli.rb
  • lib/pgbus/client.rb
  • lib/pgbus/integrations/appsignal/probe.rb
  • lib/pgbus/mcp/tools/queues_tool.rb
  • lib/pgbus/web/data_source.rb
  • lib/pgbus/web/metrics_serializer.rb
  • spec/dummy/lib/stub_data_source.rb
  • spec/integration/claimable_age_metrics_spec.rb
  • spec/pgbus/cli_spec.rb
  • spec/pgbus/client_spec.rb
  • spec/pgbus/integrations/appsignal/probe_spec.rb
  • spec/pgbus/web/data_source_batched_metrics_spec.rb
  • spec/pgbus/web/data_source_spec.rb
  • spec/pgbus/web/metrics_serializer_spec.rb
  • spec/support/pgbus/stub_data_source.rb

Comment thread lib/pgbus/client.rb
Comment thread lib/pgbus/mcp/tools/queues_tool.rb Outdated
Comment thread README.md Outdated
Comment thread spec/integration/claimable_age_metrics_spec.rb Outdated
Comment thread spec/pgbus/web/data_source_batched_metrics_spec.rb
Comment thread spec/pgbus/web/data_source_batched_metrics_spec.rb Outdated
…ength, doc clarifications

CodeRabbit review fixes on PR #390:
- Client#oldest_claimable_ages wraps the raw query in `synchronized` — on the
  shared-Proc path with_raw_connection yields the same AR connection every
  @pgmq operation uses, so an unserialized query could interleave mid-protocol
- parked depth derived once in DataSource (parked_length) instead of three views
- MCP queues_tool description: nil claimable age = nothing currently eligible
  (scheduled, backoff-parked, OR in-flight), not proof of health
- README: document that the claimable gauge omits its series when nil
- integration spec: derive queue key via config.queue_name; tolerate wall-clock
  growth between calls on a contended server
- batched-metrics spec: fixture comment matches the read_ct=0 wait:-re-enqueue
  incident shape
@mhenrixon

Copy link
Copy Markdown
Collaborator Author

Re the outside-diff comment on _queues_table.html.erb: implemented in 2a7d059parked_length is now derived once in Web::DataSource (batched_queue_metrics + queue_metrics_via_sql) and all three views read q[:parked_length] / @queue[:parked_length] instead of repeating the subtraction; stub fixtures and the batched-metrics spec assert the new field.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/views/pgbus/queues/show.html.erb`:
- Around line 16-17: Update the queue summary view around the existing parked
and oldest_claimable entries to also render `@queue`[:oldest_msg_age_sec] with its
localized oldest-message-age label and the same "—" fallback used for missing
age values. Preserve the existing summary fields and ordering while displaying
both age metrics returned by the data source.

In `@lib/pgbus/client.rb`:
- Around line 560-568: Update oldest_claimable_ages to execute its metric
queries through the bounded `@pgmq` connection, using `@pgmq.with_connection` while
preserving the existing synchronized block and query behavior. Remove the
with_raw_connection path for this method so String/Hash configurations reuse the
statement and socket bounds applied during Client#initialize.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1fd12ea5-d23e-4889-92e5-f7c4d89a91f9

📥 Commits

Reviewing files that changed from the base of the PR and between 308862b and 2a7d059.

📒 Files selected for processing (11)
  • README.md
  • app/views/pgbus/dashboard/_queues_table.html.erb
  • app/views/pgbus/queues/_queues_list.html.erb
  • app/views/pgbus/queues/show.html.erb
  • lib/pgbus/client.rb
  • lib/pgbus/mcp/tools/queues_tool.rb
  • lib/pgbus/web/data_source.rb
  • spec/dummy/lib/stub_data_source.rb
  • spec/integration/claimable_age_metrics_spec.rb
  • spec/pgbus/web/data_source_batched_metrics_spec.rb
  • spec/support/pgbus/stub_data_source.rb

Comment thread app/views/pgbus/queues/show.html.erb
Comment thread lib/pgbus/client.rb
…n, show raw age on queue detail

- Client#oldest_claimable_ages now uses @pgmq.with_connection (health-checked,
  bounded by the statement/socket timeouts from Client#initialize) instead of
  a fresh unbounded PG.connect per call — same migration notify_trigger_current?
  made; locally this cut the integration spec from ~150s to ~9s on a
  contended server
- queues/show summary line now shows the raw oldest age alongside the
  claimable age (new pgbus.queues.show.oldest key in all 12 locales)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/pgbus/client.rb (1)

557-576: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use enqueue time for oldest_claimable_age_sec.

claimable_age_for subtracts min(vt) at Line 988. This reports visibility duration, not message age. A message enqueued one hour ago and due one second ago reports about one second. lib/pgbus/web/data_source.rb, Lines 1211-1260, computes this metric from min(enqueued_at) after filtering vt <= NOW(). Replace min(vt) with min(enqueued_at) and add a regression case with an old enqueued_at and a due vt, so client and dashboard results match.

Proposed fix
-        SELECT EXTRACT(epoch FROM (NOW() - min(vt)))::int AS age_sec
+        SELECT EXTRACT(epoch FROM (NOW() - min(enqueued_at)))::int AS age_sec

Also applies to: 985-993

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/pgbus/client.rb` around lines 557 - 576, The claimable_age_for method
currently calculates age using min(vt) which measures visibility duration rather
than actual message age. Update the query in claimable_age_for to compute
min(enqueued_at) instead of min(vt) to measure the age from when messages were
originally enqueued, making the oldest_claimable_ages results consistent with
how the web dashboard computes this metric. Add a regression test case that
verifies the correct behavior with a message having an old enqueued_at and a
recent vt value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@lib/pgbus/client.rb`:
- Around line 557-576: The claimable_age_for method currently calculates age
using min(vt) which measures visibility duration rather than actual message age.
Update the query in claimable_age_for to compute min(enqueued_at) instead of
min(vt) to measure the age from when messages were originally enqueued, making
the oldest_claimable_ages results consistent with how the web dashboard computes
this metric. Add a regression test case that verifies the correct behavior with
a message having an old enqueued_at and a recent vt value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f4512a1f-eaca-4abd-906d-941dfa7fdfe1

📥 Commits

Reviewing files that changed from the base of the PR and between 2a7d059 and e067fcf.

📒 Files selected for processing (15)
  • app/views/pgbus/queues/show.html.erb
  • config/locales/da.yml
  • config/locales/de.yml
  • config/locales/en.yml
  • config/locales/es.yml
  • config/locales/fi.yml
  • config/locales/fr.yml
  • config/locales/it.yml
  • config/locales/ja.yml
  • config/locales/nb.yml
  • config/locales/nl.yml
  • config/locales/pt.yml
  • config/locales/sv.yml
  • lib/pgbus/client.rb
  • spec/pgbus/client_spec.rb

@mhenrixon mhenrixon self-assigned this Aug 4, 2026
@mhenrixon mhenrixon added the bug Something isn't working label Aug 4, 2026
@mhenrixon
mhenrixon merged commit 8c803c8 into main Aug 4, 2026
14 checks passed
@mhenrixon
mhenrixon deleted the issue-389-claimable-age-metric branch August 4, 2026 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Queue-age metrics count vt-parked (scheduled/retrying) messages, so one delayed job reads as a degraded queue

1 participant