You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by rf...@apache.org on 2026/02/25 05:44:12 UTC

(pulsar-client-go) branch master updated: feat(namespace): add removal methods for namespace policies (#1465)

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

rfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-client-go.git


The following commit(s) were added to refs/heads/master by this push:
     new 35646746 feat(namespace): add removal methods for namespace policies (#1465)
35646746 is described below

commit 3564674615ac147075a299aafa8101ccbc2846cf
Author: Rui Fu <fr...@users.noreply.github.com>
AuthorDate: Wed Feb 25 13:44:07 2026 +0800

    feat(namespace): add removal methods for namespace policies (#1465)
    
    * feat(namespace): add removal methods for namespace configs
    
    * docs(namespace): refine comment for RemoveNamespaceMessageTTLWithContext
---
 pulsaradmin/pkg/admin/namespace.go      | 98 +++++++++++++++++++++++++++++++++
 pulsaradmin/pkg/admin/namespace_test.go | 84 ++++++++++++++++------------
 2 files changed, 148 insertions(+), 34 deletions(-)

diff --git a/pulsaradmin/pkg/admin/namespace.go b/pulsaradmin/pkg/admin/namespace.go
index 1d24b5c5..05afe719 100644
--- a/pulsaradmin/pkg/admin/namespace.go
+++ b/pulsaradmin/pkg/admin/namespace.go
@@ -94,6 +94,12 @@ type Namespaces interface {
 	// GetNamespaceMessageTTLWithContext returns the message TTL for a namespace. Returns -1 if not set
 	GetNamespaceMessageTTLWithContext(ctx context.Context, namespace string) (int, error)
 
+	// RemoveNamespaceMessageTTL removes the message TTL configuration for a namespace, defaulting to broker settings
+	RemoveNamespaceMessageTTL(namespace string) error
+
+	// RemoveNamespaceMessageTTLWithContext removes the message TTL for a namespace, defaulting to broker settings
+	RemoveNamespaceMessageTTLWithContext(ctx context.Context, namespace string) error
+
 	// GetRetention returns the retention configuration for a namespace.
 	// Returns nil if the retention policy is not configured at the namespace level.
 	GetRetention(namespace string) (*utils.RetentionPolicies, error)
@@ -108,6 +114,12 @@ type Namespaces interface {
 	// SetRetentionWithContext sets the retention configuration for all the topics on a namespace
 	SetRetentionWithContext(ctx context.Context, namespace string, policy utils.RetentionPolicies) error
 
+	// RemoveRetention removes the retention configuration for a namespace, defaulting to broker settings
+	RemoveRetention(namespace string) error
+
+	// RemoveRetentionWithContext removes the retention configuration for a namespace, defaulting to broker settings
+	RemoveRetentionWithContext(ctx context.Context, namespace string) error
+
 	// GetBacklogQuotaMap returns backlog quota map on a namespace
 	GetBacklogQuotaMap(namespace string) (map[utils.BacklogQuotaType]utils.BacklogQuota, error)
 
@@ -288,6 +300,14 @@ type Namespaces interface {
 	// Returns -1 if not set
 	GetMaxConsumersPerSubscriptionWithContext(ctx context.Context, namespace utils.NameSpaceName) (int, error)
 
+	// RemoveMaxConsumersPerSubscription removes maxConsumersPerSubscription configuration for a namespace,
+	// defaulting to broker settings
+	RemoveMaxConsumersPerSubscription(namespace utils.NameSpaceName) error
+
+	// RemoveMaxConsumersPerSubscriptionWithContext removes maxConsumersPerSubscription configuration for a namespace,
+	// defaulting to broker settings
+	RemoveMaxConsumersPerSubscriptionWithContext(ctx context.Context, namespace utils.NameSpaceName) error
+
 	// SetMaxConsumersPerTopic sets maxConsumersPerTopic for a namespace.
 	//nolint: revive // It's ok here to use a built-in function name (max)
 	SetMaxConsumersPerTopic(namespace utils.NameSpaceName, max int) error
@@ -302,6 +322,14 @@ type Namespaces interface {
 	// GetMaxConsumersPerTopicWithContext returns the maxProducersPerTopic for a namespace. Returns -1 if not set
 	GetMaxConsumersPerTopicWithContext(ctx context.Context, namespace utils.NameSpaceName) (int, error)
 
+	// RemoveMaxConsumersPerTopic removes maxConsumersPerTopic configuration for a namespace,
+	// defaulting to broker settings
+	RemoveMaxConsumersPerTopic(namespace utils.NameSpaceName) error
+
+	// RemoveMaxConsumersPerTopicWithContext removes maxConsumersPerTopic configuration for a namespace,
+	// defaulting to broker settings
+	RemoveMaxConsumersPerTopicWithContext(ctx context.Context, namespace utils.NameSpaceName) error
+
 	// SetMaxProducersPerTopic sets maxProducersPerTopic for a namespace.
 	//nolint: revive // It's ok here to use a built-in function name (max)
 	SetMaxProducersPerTopic(namespace utils.NameSpaceName, max int) error
@@ -316,6 +344,14 @@ type Namespaces interface {
 	// GetMaxProducersPerTopicWithContext returns the maxProducersPerTopic for a namespace. Returns -1 if not set
 	GetMaxProducersPerTopicWithContext(ctx context.Context, namespace utils.NameSpaceName) (int, error)
 
+	// RemoveMaxProducersPerTopic removes maxProducersPerTopic configuration for a namespace,
+	// defaulting to broker settings
+	RemoveMaxProducersPerTopic(namespace utils.NameSpaceName) error
+
+	// RemoveMaxProducersPerTopicWithContext removes maxProducersPerTopic configuration for a namespace,
+	// defaulting to broker settings
+	RemoveMaxProducersPerTopicWithContext(ctx context.Context, namespace utils.NameSpaceName) error
+
 	// SetMaxTopicsPerNamespace sets maxTopicsPerNamespace for a namespace.
 	//nolint: revive // It's ok here to use a built-in function name (max)
 	SetMaxTopicsPerNamespace(namespace utils.NameSpaceName, max int) error
@@ -891,6 +927,19 @@ func (n *namespaces) SetNamespaceMessageTTLWithContext(ctx context.Context, name
 	return n.pulsar.Client.PostWithContext(ctx, endpoint, &ttlInSeconds)
 }
 
+func (n *namespaces) RemoveNamespaceMessageTTL(namespace string) error {
+	return n.RemoveNamespaceMessageTTLWithContext(context.Background(), namespace)
+}
+
+func (n *namespaces) RemoveNamespaceMessageTTLWithContext(ctx context.Context, namespace string) error {
+	nsName, err := utils.GetNamespaceName(namespace)
+	if err != nil {
+		return err
+	}
+	endpoint := n.pulsar.endpoint(n.basePath, nsName.String(), "messageTTL")
+	return n.pulsar.Client.DeleteWithContext(ctx, endpoint)
+}
+
 func (n *namespaces) SetRetention(namespace string, policy utils.RetentionPolicies) error {
 	return n.SetRetentionWithContext(context.Background(), namespace, policy)
 }
@@ -926,6 +975,19 @@ func (n *namespaces) GetRetentionWithContext(ctx context.Context, namespace stri
 	return nil, err
 }
 
+func (n *namespaces) RemoveRetention(namespace string) error {
+	return n.RemoveRetentionWithContext(context.Background(), namespace)
+}
+
+func (n *namespaces) RemoveRetentionWithContext(ctx context.Context, namespace string) error {
+	nsName, err := utils.GetNamespaceName(namespace)
+	if err != nil {
+		return err
+	}
+	endpoint := n.pulsar.endpoint(n.basePath, nsName.String(), "retention")
+	return n.pulsar.Client.DeleteWithContext(ctx, endpoint)
+}
+
 func (n *namespaces) GetBacklogQuotaMap(namespace string) (map[utils.BacklogQuotaType]utils.BacklogQuota, error) {
 	return n.GetBacklogQuotaMapWithContext(context.Background(), namespace)
 }
@@ -1171,6 +1233,18 @@ func (n *namespaces) GetMaxConsumersPerSubscriptionWithContext(
 	return result, err
 }
 
+func (n *namespaces) RemoveMaxConsumersPerSubscription(namespace utils.NameSpaceName) error {
+	return n.RemoveMaxConsumersPerSubscriptionWithContext(context.Background(), namespace)
+}
+
+func (n *namespaces) RemoveMaxConsumersPerSubscriptionWithContext(
+	ctx context.Context,
+	namespace utils.NameSpaceName,
+) error {
+	endpoint := n.pulsar.endpoint(n.basePath, namespace.String(), "maxConsumersPerSubscription")
+	return n.pulsar.Client.DeleteWithContext(ctx, endpoint)
+}
+
 func (n *namespaces) SetOffloadThreshold(namespace utils.NameSpaceName, threshold int64) error {
 	return n.SetOffloadThresholdWithContext(context.Background(), namespace, threshold)
 }
@@ -1251,6 +1325,18 @@ func (n *namespaces) GetMaxConsumersPerTopicWithContext(
 	return result, err
 }
 
+func (n *namespaces) RemoveMaxConsumersPerTopic(namespace utils.NameSpaceName) error {
+	return n.RemoveMaxConsumersPerTopicWithContext(context.Background(), namespace)
+}
+
+func (n *namespaces) RemoveMaxConsumersPerTopicWithContext(
+	ctx context.Context,
+	namespace utils.NameSpaceName,
+) error {
+	endpoint := n.pulsar.endpoint(n.basePath, namespace.String(), "maxConsumersPerTopic")
+	return n.pulsar.Client.DeleteWithContext(ctx, endpoint)
+}
+
 func (n *namespaces) SetCompactionThreshold(namespace utils.NameSpaceName, threshold int64) error {
 	return n.SetCompactionThresholdWithContext(context.Background(), namespace, threshold)
 }
@@ -1307,6 +1393,18 @@ func (n *namespaces) GetMaxProducersPerTopicWithContext(
 	return result, err
 }
 
+func (n *namespaces) RemoveMaxProducersPerTopic(namespace utils.NameSpaceName) error {
+	return n.RemoveMaxProducersPerTopicWithContext(context.Background(), namespace)
+}
+
+func (n *namespaces) RemoveMaxProducersPerTopicWithContext(
+	ctx context.Context,
+	namespace utils.NameSpaceName,
+) error {
+	endpoint := n.pulsar.endpoint(n.basePath, namespace.String(), "maxProducersPerTopic")
+	return n.pulsar.Client.DeleteWithContext(ctx, endpoint)
+}
+
 func (n *namespaces) GetNamespaceReplicationClusters(namespace string) ([]string, error) {
 	return n.GetNamespaceReplicationClustersWithContext(context.Background(), namespace)
 }
diff --git a/pulsaradmin/pkg/admin/namespace_test.go b/pulsaradmin/pkg/admin/namespace_test.go
index 1796598e..f14027dd 100644
--- a/pulsaradmin/pkg/admin/namespace_test.go
+++ b/pulsaradmin/pkg/admin/namespace_test.go
@@ -610,28 +610,23 @@ func TestNamespaces_MessageTTL(t *testing.T) {
 
 	namespace, _ := utils.GetNamespaceName("public/default")
 
-	// Get default (should be -1)
 	ttl, err := admin.Namespaces().GetNamespaceMessageTTL(namespace.String())
 	assert.NoError(t, err)
-	assert.Equal(t, -1, ttl)
+	initialTTL := ttl
 
-	// Set to 0 explicitly
-	err = admin.Namespaces().SetNamespaceMessageTTL(namespace.String(), 0)
+	err = admin.Namespaces().SetNamespaceMessageTTL(namespace.String(), 3600)
 	assert.NoError(t, err)
 
-	// Verify returns 0
 	ttl, err = admin.Namespaces().GetNamespaceMessageTTL(namespace.String())
 	assert.NoError(t, err)
-	assert.Equal(t, 0, ttl)
+	assert.Equal(t, 3600, ttl)
 
-	// Set to positive value
-	err = admin.Namespaces().SetNamespaceMessageTTL(namespace.String(), 3600)
+	err = admin.Namespaces().RemoveNamespaceMessageTTL(namespace.String())
 	assert.NoError(t, err)
 
-	// Verify returns value
 	ttl, err = admin.Namespaces().GetNamespaceMessageTTL(namespace.String())
 	assert.NoError(t, err)
-	assert.Equal(t, 3600, ttl)
+	assert.Equal(t, initialTTL, ttl)
 }
 
 func TestNamespaces_OffloadDeleteLag(t *testing.T) {
@@ -674,28 +669,50 @@ func TestNamespaces_MaxConsumersPerTopic(t *testing.T) {
 
 	namespace, _ := utils.GetNamespaceName("public/default")
 
-	// Get default (should be -1)
 	maxConsumers, err := admin.Namespaces().GetMaxConsumersPerTopic(*namespace)
 	assert.NoError(t, err)
-	assert.Equal(t, -1, maxConsumers)
+	initialMaxConsumers := maxConsumers
 
-	// Set to 0 explicitly
-	err = admin.Namespaces().SetMaxConsumersPerTopic(*namespace, 0)
+	err = admin.Namespaces().SetMaxConsumersPerTopic(*namespace, 100)
 	assert.NoError(t, err)
 
-	// Verify returns 0
 	maxConsumers, err = admin.Namespaces().GetMaxConsumersPerTopic(*namespace)
 	assert.NoError(t, err)
-	assert.Equal(t, 0, maxConsumers)
+	assert.Equal(t, 100, maxConsumers)
 
-	// Set to positive value
-	err = admin.Namespaces().SetMaxConsumersPerTopic(*namespace, 100)
+	err = admin.Namespaces().RemoveMaxConsumersPerTopic(*namespace)
 	assert.NoError(t, err)
 
-	// Verify returns value
 	maxConsumers, err = admin.Namespaces().GetMaxConsumersPerTopic(*namespace)
 	assert.NoError(t, err)
+	assert.Equal(t, initialMaxConsumers, maxConsumers)
+}
+
+func TestNamespaces_MaxConsumersPerSubscription(t *testing.T) {
+	config := &config.Config{}
+	admin, err := New(config)
+	require.NoError(t, err)
+	require.NotNil(t, admin)
+
+	namespace, _ := utils.GetNamespaceName("public/default")
+
+	maxConsumers, err := admin.Namespaces().GetMaxConsumersPerSubscription(*namespace)
+	assert.NoError(t, err)
+	initialMaxConsumers := maxConsumers
+
+	err = admin.Namespaces().SetMaxConsumersPerSubscription(*namespace, 100)
+	assert.NoError(t, err)
+
+	maxConsumers, err = admin.Namespaces().GetMaxConsumersPerSubscription(*namespace)
+	assert.NoError(t, err)
 	assert.Equal(t, 100, maxConsumers)
+
+	err = admin.Namespaces().RemoveMaxConsumersPerSubscription(*namespace)
+	assert.NoError(t, err)
+
+	maxConsumers, err = admin.Namespaces().GetMaxConsumersPerSubscription(*namespace)
+	assert.NoError(t, err)
+	assert.Equal(t, initialMaxConsumers, maxConsumers)
 }
 
 func TestNamespaces_CompactionThreshold(t *testing.T) {
@@ -738,28 +755,23 @@ func TestNamespaces_MaxProducersPerTopic(t *testing.T) {
 
 	namespace, _ := utils.GetNamespaceName("public/default")
 
-	// Get default (should be -1)
 	maxProducers, err := admin.Namespaces().GetMaxProducersPerTopic(*namespace)
 	assert.NoError(t, err)
-	assert.Equal(t, -1, maxProducers)
+	initialMaxProducers := maxProducers
 
-	// Set to 0 explicitly
-	err = admin.Namespaces().SetMaxProducersPerTopic(*namespace, 0)
+	err = admin.Namespaces().SetMaxProducersPerTopic(*namespace, 50)
 	assert.NoError(t, err)
 
-	// Verify returns 0
 	maxProducers, err = admin.Namespaces().GetMaxProducersPerTopic(*namespace)
 	assert.NoError(t, err)
-	assert.Equal(t, 0, maxProducers)
+	assert.Equal(t, 50, maxProducers)
 
-	// Set to positive value
-	err = admin.Namespaces().SetMaxProducersPerTopic(*namespace, 50)
+	err = admin.Namespaces().RemoveMaxProducersPerTopic(*namespace)
 	assert.NoError(t, err)
 
-	// Verify returns value
 	maxProducers, err = admin.Namespaces().GetMaxProducersPerTopic(*namespace)
 	assert.NoError(t, err)
-	assert.Equal(t, 50, maxProducers)
+	assert.Equal(t, initialMaxProducers, maxProducers)
 }
 
 func TestNamespaces_Retention(t *testing.T) {
@@ -770,12 +782,10 @@ func TestNamespaces_Retention(t *testing.T) {
 
 	namespaceName := "public/default"
 
-	// Initial state: policy not configured, should return nil
 	retention, err := admin.Namespaces().GetRetention(namespaceName)
 	assert.NoError(t, err)
-	assert.Nil(t, retention, "Expected nil when retention is not configured")
+	initialRetention := retention
 
-	// Set new retention policy
 	newRetention := utils.RetentionPolicies{
 		RetentionSizeInMB:      1024,
 		RetentionTimeInMinutes: 60,
@@ -783,12 +793,18 @@ func TestNamespaces_Retention(t *testing.T) {
 	err = admin.Namespaces().SetRetention(namespaceName, newRetention)
 	assert.NoError(t, err)
 
-	// Verify retention is set
 	retention, err = admin.Namespaces().GetRetention(namespaceName)
 	assert.NoError(t, err)
-	assert.NotNil(t, retention, "Expected non-nil when retention is configured")
+	assert.NotNil(t, retention)
 	assert.Equal(t, int64(1024), retention.RetentionSizeInMB)
 	assert.Equal(t, 60, retention.RetentionTimeInMinutes)
+
+	err = admin.Namespaces().RemoveRetention(namespaceName)
+	assert.NoError(t, err)
+
+	retention, err = admin.Namespaces().GetRetention(namespaceName)
+	assert.NoError(t, err)
+	assert.Equal(t, initialRetention, retention)
 }
 
 func TestNamespaces_BookieAffinityGroup(t *testing.T) {