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]

Reply via email to