Service Bus message peek in Playground and Message Flow¶
Motivation¶
Messages enqueued from the Service Bus Playground were visible in the Azure
portal queue but never surfaced in the dashboard. The Playground could send and
drain messages but had no way to view the content of messages that were sitting
in the queue, and the Message Flow card only renders active jobstate Table
rows — never the raw queue messages. When messages lingered (consumer not
running, Manage claim missing for counts), the operator saw "no active messages"
in the dashboard while the portal clearly showed queued messages.
A non-destructive peek closes this gap. Peek uses only the data-plane
Azure Service Bus Data Receiver claim, so it works even when the admin
(Manage) claim needed for entity counts is unavailable and counts degrade to
no_manage_claim.
User-facing change¶
- Service Bus Playground: a new "Peek messages" button in the Consumer pane lists the messages currently in the request queue without removing them — showing program, db, correlation/request id, and a sanitised, size-bounded body preview. Peek auto-refreshes after a send or drain when results are already open.
- Message Flow: the expanded modal now shows a "Queued messages" section listing the same peeked count + sanitised content. The compact card shows "N queued messages" instead of "no active messages" when the queue is non-empty but no jobs are in flight.
API / IaC diff summary¶
api/services/service_bus.py: added_preview_messageandpeek_request_previews(cfg, max_count)— sanitised, size-bounded (_PEEK_BODY_MAX_CHARS = 4000) JSON-safe previews built on the existing data-planepeek_requests(no settlement, no Manage claim).api/routes/settings/service_bus.py: addedGET /api/settings/service-bus/peek(Reader-accessible, degrades gracefully, returns{available, reason?, detail?, queue, messages, count}).api/tests/persona_reader_allowlist.py: whitelisted the newpeekroute for the Reader persona.api/services/message_flow.py:build_message_flownow includes a bounded (_QUEUE_PREVIEW_LIMIT = 10)queue_messagespreview, peeked only when counts are available or the only gap is the Manage claim (never a second slow connect when the namespace is unreachable).web/src/api/settings.ts,web/src/api/messageFlow.ts: newServiceBusPeekMessage/ServiceBusPeekResponsetypes,peekServiceBusclient, and optionalqueue_messagesonMessageFlowSnapshot.web/src/pages/ServiceBusPlayground.tsx,web/src/components/cards/MessageFlow/MessageFlowModal.tsx,web/src/components/cards/MessageFlow/MessageFlowCard.tsx: UI wiring.
No IaC change. No new SAS token is issued to the browser; all peek traffic flows
through the api sidecar under the shared managed identity.
Validation evidence¶
uv run ruff check api→ All checks passed.uv run pytest -q api/tests→ 3829 passed, 3 skipped.- New
api/tests/test_service_bus_peek.py(preview shaping, truncation, route degrade/available/auth-failure). - Extended
api/tests/test_message_flow.py(queue_messages included; peek skipped when unreachable; peek runs when only the Manage claim is missing). cd web && npm run build→ built successfully.cd web && npm run lint→ clean.