This is an automated email from the ASF dual-hosted git repository.

lhotari pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/pulsar.git

commit a94a4c5a0e2ed3c6f5e2ca70b1079fffd361c707
Author: Lari Hotari <[email protected]>
AuthorDate: Fri Jul 3 02:57:11 2026 +0300

    [fix][broker][branch-4.0] Fix NOT_FOUND for topic policy operations on idle 
non-persistent topics
    
    ### Motivation
    
    On branch-4.0, topic-level policy admin operations run 
`PersistentTopicsBase#preValidation`,
    which checks topic existence via `AdminResource#checkTopicExistsAsync`. For 
non-persistent
    topics that check lists topics through 
`NamespaceService#getListOfNonPersistentTopics`, which
    only returns "active" non-persistent topics (those with producers, 
consumers or subscriptions).
    A freshly created or otherwise idle non-persistent topic has none of these, 
so it was reported
    as non-existent and the operation failed with `404 NOT_FOUND` -- for example
    `admin.topicPolicies().setMaxSubscriptionsPerTopic(topic, 10)` immediately 
after
    `admin.topics().createNonPartitionedTopic(topic)`.
    
    This is branch-4.0 specific. On master and branch-4.2 it is already fixed 
by #24225
    ("Allow recreation of partitioned topic after metadata loss"), which rewrote
    `checkTopicExistsAsync` to delegate to 
`NamespaceService#checkTopicExistsAsync`. #24225 was
    never backported to branch-4.0.
    
    Surfaced by 
`TopicPoliciesTest#testNonPersistentTopicAppliesTopicPolicyOnLoad` (added by 
#26134),
    which fails on branch-4.0 but passes on master/branch-4.2.
    
    ### Modifications
    
    In `AdminResource#checkTopicExistsAsync`, resolve non-persistent topic 
existence through
    `NamespaceService#checkTopicExistsAsync`, which detects a loaded 
non-persistent topic via the
    owner broker's in-memory topic map (no "active" filter). Persistent-topic 
handling is unchanged.
---
 .../java/org/apache/pulsar/broker/admin/AdminResource.java | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java
index dd45ac3c94c..03fa76e48bf 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java
@@ -748,6 +748,20 @@ public abstract class AdminResource extends 
PulsarWebResource {
      * @param topicName given topic name
      */
     protected CompletableFuture<Boolean> checkTopicExistsAsync(TopicName 
topicName) {
+        if (!topicName.isPersistent()) {
+            // For non-persistent topics, resolve existence via 
NamespaceService#checkTopicExistsAsync, which
+            // consults the owner broker's in-memory topic map. The list-based 
path below (getListOfTopics ->
+            // getListOfNonPersistentTopics) only reports "active" 
non-persistent topics -- those with producers,
+            // consumers or subscriptions -- so an idle non-persistent topic 
(e.g. just created) would be treated
+            // as non-existent, making its topic-policy admin operations fail 
with 404 NOT_FOUND.
+            // branch-4.0-only workaround; branch-4.1+ fix this via 
apache/pulsar#24225, not backported to branch-4.0.
+            return 
pulsar().getNamespaceService().checkTopicExistsAsync(topicName).thenApply(topicExistsInfo
 -> {
+                boolean exists = topicExistsInfo.isExists();
+                topicExistsInfo.recycle();
+                return exists;
+            });
+        }
+
         return 
pulsar().getNamespaceService().getListOfTopics(topicName.getNamespaceObject(),
                 CommandGetTopicsOfNamespace.Mode.ALL)
                 .thenCompose(topics -> {

Reply via email to