Skip to content

feat(replay): bulk message replay / DLQ triage (UI, REST, CLI, MCP) - #5

Merged
ritikbansod merged 1 commit into
mainfrom
feat/dlq-replay
Sep 28, 2026
Merged

ritikbansod merged 1 commit into
mainfrom
feat/dlq-replay

Conversation

@ritikbansod

Copy link
Copy Markdown
Owner

Implements F3 — bulk message replay / DLQ triage from the deep analysis, fulfilling the README roadmap's "Message replay: copy a filtered set of messages to another topic or cluster". Stacked on #4 — merge #1 → #2 → #3 → #4 → this.

What it does

POST /api/clusters/{clusterId}/topics/{topic}/replay selects messages from a source topic (typically a DLQ) with the browser's read-only scan — keyContains/valueContains filters, oldest first — and produces them to a target topic on the same or a different connected cluster, preserving keys, headers and original timestamps (so offset-reset semantics stay meaningful after replay).

  • dryRun: true previews the selection without producing — the recommended first step.
  • Bounded: max 1000 messages per call; reachedEnd tells you whether the whole source was covered.
  • Fail-fast on the first produce error, with the source partition@offset in the error list, so a re-run with a narrowed filter can continue.

Safety integration is free — replay is a real mutation, so the chain from #2/#3 applies automatically: admin role only in authenticated modes, every call lands in the mutation audit log, refused outright in KVIEW_READONLY=true mode. The MCP tool additionally carries the same confirm=true guard as topic delete (replaying duplicates messages — the AI is told to dryRun first).

Surfaces

  • Web UI: Replay tab in the data explorer — target topic/cluster, filters, limit, headers toggle, dry-run checkbox, outcome summary.
  • CLI: kview replay <sourceTopic> --to-topic T [--to-cluster ID] [--limit N] [--dry-run] [--no-headers].
  • MCP: kview_replay_messages — 19 tools now.

Bonus fix

MessageBrowserService.browse never stopped early when the topic was smaller than the limit — it polled until the deadline (up to 60s). It now stops as soon as every assigned partition reaches its end offset; small topics answer immediately, and reachedEnd is exact. (The browser test suite dropped from 34s to 15s.)

Verification

  • 3 new integration tests against an embedded broker: same-cluster copy (20/20, header retry=3 and original timestamp preserved, all keys present), dry-run selects 4 poison messages without producing then the real filtered run copies exactly those, cross-connection replay through a second stored profile read back via that connection's own handle.
  • Full suite: 56/56 green; CLI and MCP smokes pass (19 tools; replay refuses without confirm=true).
  • Not covered: binary (non-UTF-8) header values are transported as text — documented limitation; headers are re-encoded UTF-8 on the target.

Implements F3 from the deep analysis — the README roadmap's message replay
promise: copy a filtered set of messages to another topic, on the same or a
different connected cluster.

- POST /api/clusters/{id}/topics/{topic}/replay: selects with the browser's
  read-only scan (key/value-contains filters, oldest first, max 1000 per
  call) and copies keys, headers and original timestamps preserved; dryRun
  previews the selection without producing. Fail-fast on the first produce
  error, with the source location in the error list.
- A real mutation, so the safety chain gates it for free: admin role only,
  mutation audit trail, refused in global read-only mode.
- Web UI: Replay tab in the data explorer (target topic/cluster, filters,
  dry-run checkbox).
- CLI: kview replay <topic> --to-topic T [--to-cluster ID] [--dry-run].
- MCP: kview_replay_messages with the same confirm=true guard as topic
  delete — 19 tools now.
- browse improvement: the scan now stops as soon as every assigned partition
  reaches its end offset instead of polling until the deadline — small
  topics answer immediately (the browser test suite dropped from 34s to 15s).
- tests: 3 integration tests (same-cluster copy with header/timestamp
  preservation, dry-run + filtered replay, cross-connection replay via a
  second stored profile). Full suite 56/56.
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.

1 participant