Skip to content

feat(queue): add lease-owner metrics and processing logs - #736

Merged
behinddwalls merged 2 commits into
mainfrom
preetam/messagequeue-metrics
Sep 22, 2026
Merged

behinddwalls merged 2 commits into
mainfrom
preetam/messagequeue-metrics

Conversation

@behinddwalls

@behinddwalls behinddwalls commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Why?

Lease ownership was only visible in the DB and the admin CLI. Renewals were a silent batch update, steals had no event, and process logs carried message_id and partition_key but not which replica held the lease — so "who owns this key" and "which node processed this message" were hard to answer from metrics or logs.

What?

Subscriber metrics tag leased_by, topic, tenant, and consumer_group, and deliberately never partition_key: acquire/steal/release counters, renew row counts, partitions_owned on every discovery, and active_subscribers plus fair_share_cap only after a successful lease-tick heartbeat query. A cap of 0 means unlimited internally; the gauge instead reports the size of the owned-plus-discovered partition set, so partitions_owned > fair_share_cap cannot fire trivially on a lone replica. Info logs cover steals (previous_owner from the pre-acquire snapshot), the release reason, and a per-tick summary even when renew fails; a first claim stays at Debug.

Release counters report effect rather than intent. ReleaseLease returns rows deleted alongside its error — it already computed the count and discarded it — so the rebalance and idle counters skip a release whose DELETE matched nothing, which happens whenever the lease was stolen or purged between the tick's read and the release. Shutdown releases one tenant at a time so the count carries a tenant tag and a failure names the tenant it belongs to. The idle path records the release as soon as the lease row is gone, before offset cleanup, so a DeleteOffset failure no longer suppresses a counter for a lease that genuinely was released.

Deliveries carry leased_by and consumer_group in metadata. The consumer snapshots those fields once before handing the delivery to the controller, because Metadata() exposes a map the controller can write to, and reuses that snapshot on the process, hold-ignored, reject, and nack logs so every line agrees on the owner.

Test Plan

✅ go test -race ./platform/extension/messagequeue/mysql/ ./platform/consumer/
✅ make fmt, make gazelle, make mocks, make check-gazelle

## Summary

### Why?

Lease ownership was only visible in the DB and the admin CLI. Renewals were a silent batch update, steals had no event, and process logs carried message_id and partition_key but not which replica held the lease — so "who owns this key" and "which node processed this message" were hard to answer from metrics or logs.

### What?

Subscriber metrics tag leased_by, topic, tenant, and consumer_group, and deliberately never partition_key: acquire/steal/release counters, renew row counts, partitions_owned on every discovery, and active_subscribers plus fair_share_cap only after a successful lease-tick heartbeat query. A cap of 0 means unlimited internally; the gauge instead reports the size of the owned-plus-discovered partition set, so `partitions_owned > fair_share_cap` cannot fire trivially on a lone replica. Info logs cover steals (previous_owner from the pre-acquire snapshot), the release reason, and a per-tick summary even when renew fails; a first claim stays at Debug.

Release counters report effect rather than intent. `ReleaseLease` returns rows deleted alongside its error — it already computed the count and discarded it — so the rebalance and idle counters skip a release whose DELETE matched nothing, which happens whenever the lease was stolen or purged between the tick's read and the release. Shutdown releases one tenant at a time so the count carries a tenant tag and a failure names the tenant it belongs to. The idle path records the release as soon as the lease row is gone, before offset cleanup, so a DeleteOffset failure no longer suppresses a counter for a lease that genuinely was released.

Deliveries carry leased_by and consumer_group in metadata. The consumer snapshots those fields once before handing the delivery to the controller, because Metadata() exposes a map the controller can write to, and reuses that snapshot on the process, hold-ignored, reject, and nack logs so every line agrees on the owner.

## Test Plan

✅ `go test -race ./platform/extension/messagequeue/mysql/ ./platform/consumer/`
✅ `make fmt`, `make gazelle`, `make mocks`, `make check-gazelle`
@behinddwalls
behinddwalls force-pushed the preetam/messagequeue-metrics branch from 17e5a7e to 6b3aecf Compare September 22, 2026 01:24
@behinddwalls
behinddwalls marked this pull request as ready for review September 22, 2026 18:19
@behinddwalls
behinddwalls requested review from a team and sbalabanov as code owners September 22, 2026 18:19
Comment thread platform/extension/messagequeue/mysql/subscriber.go
## Summary

### Why?

PR #736 made `processDelivery` always call `delivery.Metadata()` for lease-owner log fields. `TestPrimaryConsumer_GitFailureDisposition` did not expect that call, so gomock failed on the consumer goroutine while the test blocked on `<-done` until Bazel's 300s timeout.

### What?

Add `Metadata().Return(nil).AnyTimes()` to the runway mock delivery, matching the consumer package's `setupDelivery` helper.

## Test Plan

✅ `go test ./service/runway/server/ -count=1 -run TestPrimaryConsumer_GitFailureDisposition`

@mnoah1 mnoah1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approve pending updates to remove pid from the tags

@behinddwalls
behinddwalls added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit cc691c4 Sep 22, 2026
16 checks passed
@behinddwalls
behinddwalls deleted the preetam/messagequeue-metrics branch September 22, 2026 19:09

This branch was successfully deployed

1 active deployment
stack-rebase — 415bf762 Deployed Sep 22, 2026 by behinddwalls via Rebase Stack #526
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants