merlimat opened a new pull request, #25717:
URL: https://github.com/apache/pulsar/pull/25717
## Summary
Supersedes #25709, which had the right intent but produced an invalid
`persistent://t/n/parent/{descriptor}` URL that `TopicName` parses as a legacy
V1 topic name and rejects synchronously — making the admin call hard-fail
before any HTTP request goes out.
`createSubscription` / `deleteSubscription` on a scalable topic was silently
broken before either change.
`ScalableTopicController.createSubscriptionOnSegment` built a
`persistent://t/n/parent` URL (no descriptor) and handed it to the generic
`topics().createSubscriptionAsync` admin API. That URL addresses the parent
scalable topic, which has no managed-ledger backing, so the admin call hit
`Subscription Busy` / `NotFound` and the `.exceptionally` block swallowed it.
Per-segment cursors were never pre-created. Lazy cursor creation by the V5
client on first consumer subscribe masked the bug in the happy path; admin
`createSubscription` had no observable effect beyond writing the
`SubscriptionMetadata` to the metadata store. The same shape of bug existed in
`ScalableTopics.deleteSegmentTopics` (whole-scalable-topic teardown).
The clean fix is segment-specific admin endpoints, all the way down — no
`persistent://` conversion.
### New REST endpoints (`Segments.java`, super-user only, segment-domain
only)
- `PUT
/segments/{tenant}/{namespace}/{topic}/{descriptor}/subscription/{subscription}`
— create a cursor at earliest position
- `DELETE
/segments/{tenant}/{namespace}/{topic}/{descriptor}/subscription/{subscription}`
— delete the cursor
Same `validateSuperUserAccessAsync` → `validateTopicOwnershipAsync` →
`getOrCreateTopic` (or `getTopicIfExists` for delete) pattern as the existing
`/segments/.../subscription/{sub}/backlog`, `/seek`, `/skip-all`.
### New admin client methods (`ScalableTopics`)
- `createSegmentSubscriptionAsync(segmentTopic, subscription)`
- `deleteSegmentSubscriptionAsync(segmentTopic, subscription)`
Both take a `segment://...` URI directly. `ScalableTopicsImpl` builds the
REST path from `TopicName` parts — same pattern as the existing
`getSegmentSubscriptionBacklogAsync` / `seekSegmentSubscriptionAsync` /
`clearSegmentSubscriptionBacklogAsync` helpers.
### Caller updates
- `ScalableTopicController.createSubscriptionOnSegment` /
`deleteSubscriptionOnSegment` now call
`scalableTopics().createSegmentSubscriptionAsync` /
`deleteSegmentSubscriptionAsync`. Removed the broken
`toSegmentUnderlyingPersistentName` helper.
- `ScalableTopics.deleteSegmentTopics` (whole-scalable-topic teardown) now
uses `admin.scalableTopics().deleteSegmentAsync(segmentTopicName, force)` — the
existing segment-aware admin endpoint already used for split-segment teardown —
instead of fabricating a `persistent://` URL.
## Test plan
- [x] `V5ScalableSubscriptionAdminTest` (new, 1 test) — behavioral round
trip: create scalable topic → `admin.scalableTopics().createSubscription` →
produce 30 messages with no consumer attached → subscribe and assert all 30 are
received. **Fails on master**, **passes here**.
- [x] `ScalableTopicControllerTest` 31/31 — updated mocks:
`topics.createSubscriptionAsync` / `deleteSubscriptionAsync` →
`scalableTopics.createSegmentSubscriptionAsync` /
`deleteSegmentSubscriptionAsync`. Verifies the controller calls the new admin
path.
- [x] `ScalableTopicServiceTest` 16/16 — unchanged, no regressions.
- [x] Full V5 broker test suite green (153/153).
- [x] `pulsar-client-admin-api`, `pulsar-client-admin-original`,
`pulsar-broker` checkstyle clean.
--
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]