pilichoumao opened a new pull request, #5116:
URL: https://github.com/apache/rocketmq-dashboard/pull/5116
### Which Issue(s) This PR Fixes
No tracking issue. Follow-up completing the LiteTopic tool domain added in
#4771: the three read tools expose pattern state, session detail and the quota
watermark, but the one operation the console offers on that data — extending
the TTL of a registered Lite parent topic (`POST /api/liteTopic/extendTTL`) —
had no tool, so an MCP/CLI operator could see a pattern approaching expiry and
could not act on it.
### Brief Description
Add `rmq.litetopic.extend_ttl` (`rmqctl litetopic extend-ttl`), an **L2
mutation** over the existing `LiteTopicService.extendTTL` — no new endpoint,
service, dependency or configuration.
- **Standard two-phase mutation**: dry-run returns the plan +
`confirm_token`; apply goes through `ToolMutationFilter` (token
verification/consumption per the current trunk semantics). It is the LiteTopic
domain's first mutation and deliberately the only one.
- **Instance-scoped, ownership-guarded**: unlike the read tools
(platform-level default cluster), this follows #5006 — `extendTTL(instanceId,
…)` runs the `ResourceOwnershipGuard`, so the tool requires `instanceId` and
inherits the guard's rejections (unregistered resource → 404, non-LITE parent →
409) as honest apply failures, never silent successes.
- **Drift-free preview by construction**: the plan is derived from the
request alone — no broker state is read in `preview` — so what the caller
confirms cannot change underneath them before apply (current pattern state is
the read tools' job). `before` stays empty; `after` carries `{topicPattern,
newTtlMillis}`.
- **Deterministic broker-behavior warnings**: one-minute TTL granularity and
the 30-day cap are surfaced as plan warnings computed from the input, so the
caller sees the rounding/clamping before confirming instead of discovering it
after.
- Output reports the requested value (`{topicPattern, newTtlMillis}`); the
catalog description documents the broker-side granularity/cap.
### How Did You Test This Change?
- **Unit:** `LiteTopicExtendTtlToolHandlerTest` — preview derived from the
request without touching the service/broker (`verifyNoInteractions`),
summary/after shape, no warnings for a whole-minute value inside the cap,
granularity warning for an unaligned value, cap warning above 30 days (and none
at exactly 30 days), execute delegates `(instanceId, topicPattern,
newTtlMillis)` to the guarded service and maps the output.
- **Contract:** PLANNED + EXECUTED samples added to
`ToolOutputSchemaContractTest`; the yaml entry validates against
`rmq-tools.schema.json` on every catalog load; the rmqctl generator enforces
the instanceId convention (`make catalog-verify` clean).
- **Build:** Java 21, `mvn -B -ntp -Dspring.profiles.active=dev clean
package` — **3,291 tests, 0 Checkstyle violations**; the single error is
`ResourceOwnershipGuardTest#migrationConcurrentStartupIsIdempotentTest`, which
fails identically on pristine trunk (H2 concurrent-startup race, documented in
#4769's thread); `go test ./...`, `gofmt`, `go vet` clean. Packaging verified
with `-Dmaven.antrun.skip=true` because #5007's `binary-license-gate` fails
identically on pristine trunk in this environment.
- **End-to-end against a real local Apache RocketMQ 5.5.0
NameServer/Broker** with this branch's jar, a Studio-registered DIRECT
instance, and the real tool HTTP API:
- created a real LITE parent topic through the trunk `rmq.topic.update`
tool (`type=LITE`, which also registers resource ownership), then `extend_ttl`
dry-run → `200 PLANNED` (empty warnings for the aligned value) → apply with the
token → **`200 EXECUTED`**, with the provider logging `Extended LiteTopic TTL
to 3600000ms (60 min) for parent topic LiteParentSmoke2 on 1 broker(s)`;
- unaligned `90000ms` preview carried the one-minute-granularity warning;
- apply without a token → `400 INVALID_ARGUMENT` (mutation gate);
- apply on a NORMAL-type topic → honest `404 Lite parent topic not found`;
apply before ownership registration → honest `404 Resource ownership is not
registered yet` (guard semantics of #5006 observed end to end);
- all temporary JVMs were shut down afterwards.
Not exercised: multi-master clusters (the provider's
read-all-masters-before-write path has its own coverage), CLOUD instances,
ACL/TLS, and token replay/single-use semantics (tracked by #4665, which this
tool will inherit untouched).
### CI Status
The repository's Actions policy still rejects action versions referenced by
the existing workflow, so GitHub-hosted runs end in `startup_failure` before
any job starts (same as #4550/#4665/#4771). This PR does not change the
workflow; all results above are local.
### Checklist
- [x] One coherent change; no unrelated modifications
- [x] Conventional commit subject; regression tests use `...Test`
- [x] Tool schema validates; PLANNED/EXECUTED contract samples included
- [x] No invented metadata; guard rejections surface honestly; broker
rounding/clamping disclosed in the plan
- [x] Architecture and formatting checks pass (0 Checkstyle violations;
gofmt/vet clean)
- [x] rmqctl catalog regenerated and verified; no new dependency, port or
configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]