Copilot commented on code in PR #1451:
URL: https://github.com/apache/pulsar-client-go/pull/1451#discussion_r2625320194


##########
pulsaradmin/pkg/utils/data.go:
##########
@@ -410,18 +412,20 @@ type CursorStats struct {
 }
 
 type PartitionedTopicStats struct {
-       MsgRateIn           float64                      `json:"msgRateIn"`
-       MsgRateOut          float64                      `json:"msgRateOut"`
-       MsgThroughputIn     float64                      
`json:"msgThroughputIn"`
-       MsgThroughputOut    float64                      
`json:"msgThroughputOut"`
-       AverageMsgSize      float64                      `json:"averageMsgSize"`
-       StorageSize         int64                        `json:"storageSize"`
-       Publishers          []PublisherStats             `json:"publishers"`
-       Subscriptions       map[string]SubscriptionStats `json:"subscriptions"`
-       Replication         map[string]ReplicatorStats   `json:"replication"`
-       DeDuplicationStatus string                       
`json:"deduplicationStatus"`
-       Metadata            PartitionedTopicMetadata     `json:"metadata"`
-       Partitions          map[string]TopicStats        `json:"partitions"`
+       MsgRateIn              float64                      `json:"msgRateIn"`
+       MsgRateOut             float64                      `json:"msgRateOut"`
+       MsgThroughputIn        float64                      
`json:"msgThroughputIn"`
+       MsgThroughputOut       float64                      
`json:"msgThroughputOut"`
+       AverageMsgSize         float64                      
`json:"averageMsgSize"`
+       StorageSize            int64                        `json:"storageSize"`
+       Publishers             []PublisherStats             `json:"publishers"`
+       Subscriptions          map[string]SubscriptionStats 
`json:"subscriptions"`
+       Replication            map[string]ReplicatorStats   `json:"replication"`
+       DeDuplicationStatus    string                       
`json:"deduplicationStatus"`
+       Metadata               PartitionedTopicMetadata     `json:"metadata"`
+       Partitions             map[string]TopicStats        `json:"partitions"`
+       TopicCreationTimeStamp int64                        
`json:"topicCreationTimeStamp,omitempty"`

Review Comment:
   The field name uses "TimeStamp" (capital S) which is inconsistent with Go 
naming conventions and with other timestamp fields in this codebase. All other 
timestamp fields use "Timestamp" with lowercase 's' (e.g., LastPublishTimestamp 
on line 428, LastConsumedTimestamp, LastAckedTimestamp, etc.). Consider 
renaming this field to "TopicCreationTimestamp" for consistency, unless the 
JSON tag "topicCreationTimeStamp" is dictated by the Pulsar broker API (in 
which case only the Go field name should change).
   ```suggestion
        TopicCreationTimestamp int64                        
`json:"topicCreationTimeStamp,omitempty"`
   ```



##########
pulsaradmin/pkg/utils/data.go:
##########
@@ -229,19 +229,21 @@ type NamespacesData struct {
 }
 
 type TopicStats struct {
-       BacklogSize         int64                        `json:"backlogSize"`
-       MsgCounterIn        int64                        `json:"msgInCounter"`
-       MsgCounterOut       int64                        `json:"msgOutCounter"`
-       MsgRateIn           float64                      `json:"msgRateIn"`
-       MsgRateOut          float64                      `json:"msgRateOut"`
-       MsgThroughputIn     float64                      
`json:"msgThroughputIn"`
-       MsgThroughputOut    float64                      
`json:"msgThroughputOut"`
-       AverageMsgSize      float64                      `json:"averageMsgSize"`
-       StorageSize         int64                        `json:"storageSize"`
-       Publishers          []PublisherStats             `json:"publishers"`
-       Subscriptions       map[string]SubscriptionStats `json:"subscriptions"`
-       Replication         map[string]ReplicatorStats   `json:"replication"`
-       DeDuplicationStatus string                       
`json:"deduplicationStatus"`
+       BacklogSize            int64                        `json:"backlogSize"`
+       MsgCounterIn           int64                        
`json:"msgInCounter"`
+       MsgCounterOut          int64                        
`json:"msgOutCounter"`
+       MsgRateIn              float64                      `json:"msgRateIn"`
+       MsgRateOut             float64                      `json:"msgRateOut"`
+       MsgThroughputIn        float64                      
`json:"msgThroughputIn"`
+       MsgThroughputOut       float64                      
`json:"msgThroughputOut"`
+       AverageMsgSize         float64                      
`json:"averageMsgSize"`
+       StorageSize            int64                        `json:"storageSize"`
+       Publishers             []PublisherStats             `json:"publishers"`
+       Subscriptions          map[string]SubscriptionStats 
`json:"subscriptions"`
+       Replication            map[string]ReplicatorStats   `json:"replication"`
+       DeDuplicationStatus    string                       
`json:"deduplicationStatus"`
+       TopicCreationTimeStamp int64                        
`json:"topicCreationTimeStamp,omitempty"`

Review Comment:
   The field name uses "TimeStamp" (capital S) which is inconsistent with Go 
naming conventions and with other timestamp fields in this codebase. All other 
timestamp fields use "Timestamp" with lowercase 's' (e.g., LastPublishTimestamp 
on line 246, LastConsumedTimestamp, LastAckedTimestamp, etc.). Consider 
renaming this field to "TopicCreationTimestamp" for consistency, unless the 
JSON tag "topicCreationTimeStamp" is dictated by the Pulsar broker API (in 
which case only the Go field name should change).
   ```suggestion
        TopicCreationTimestamp int64                        
`json:"topicCreationTimeStamp,omitempty"`
   ```



##########
pulsaradmin/pkg/admin/topic_test.go:
##########
@@ -1554,3 +1554,103 @@ func TestTopics_PublishRate(t *testing.T) {
                100*time.Millisecond,
        )
 }
+
+func TestTopicStatsTimestamps(t *testing.T) {
+       topic := 
fmt.Sprintf("persistent://public/default/test-topic-stats-timestamps-%d", 
time.Now().Nanosecond())
+       cfg := &config.Config{}
+       admin, err := New(cfg)
+       assert.NoError(t, err)
+
+       topicName, err := utils.GetTopicName(topic)
+       assert.NoError(t, err)
+
+       // Create topic
+       err = admin.Topics().Create(*topicName, 0)
+       assert.NoError(t, err)
+       defer admin.Topics().Delete(*topicName, true, true)
+
+       // Get stats and verify CreationTimestamp
+       stats, err := admin.Topics().GetStats(*topicName)
+       assert.NoError(t, err)
+       assert.Greater(t, stats.TopicCreationTimeStamp, int64(0), 
"CreationTimestamp should be greater than 0")
+       // LastPublishTimestamp should be 0 before any message is published
+       assert.Equal(t, int64(0), stats.LastPublishTimestamp, 
"LastPublishTimestamp should be 0 initially")
+
+       // Publish a message
+       client, err := pulsar.NewClient(pulsar.ClientOptions{
+               URL: lookupURL,
+       })
+       assert.NoError(t, err)
+       defer client.Close()
+
+       producer, err := client.CreateProducer(pulsar.ProducerOptions{
+               Topic: topic,
+       })
+       assert.NoError(t, err)
+       defer producer.Close()
+
+       ctx := context.Background()
+       _, err = producer.Send(ctx, &pulsar.ProducerMessage{
+               Payload: []byte("test-message"),
+       })
+       assert.NoError(t, err)
+
+       // Wait for stats to update (stats are updated asynchronously in broker)
+       assert.Eventually(t, func() bool {
+               s, err := admin.Topics().GetStats(*topicName)
+               if err != nil {
+                       return false
+               }
+               return s.LastPublishTimestamp > 0
+       }, 10*time.Second, 500*time.Millisecond, "LastPublishTimestamp should 
update after publishing")
+}
+
+func TestPartitionedTopicStatsTimestamps(t *testing.T) {
+       topic := 
fmt.Sprintf("persistent://public/default/test-partitioned-topic-stats-timestamps-%d",
 time.Now().Nanosecond())
+       cfg := &config.Config{}
+       admin, err := New(cfg)
+       assert.NoError(t, err)
+
+       topicName, err := utils.GetTopicName(topic)
+       assert.NoError(t, err)
+
+       // Create partitioned topic
+       err = admin.Topics().Create(*topicName, 2)
+       assert.NoError(t, err)
+       defer admin.Topics().Delete(*topicName, true, true)
+
+       // Get partitioned stats and verify CreationTimestamp
+       stats, err := admin.Topics().GetPartitionedStats(*topicName, true)
+       assert.NoError(t, err)
+       assert.Greater(t, stats.TopicCreationTimeStamp, int64(0), 
"CreationTimestamp should be greater than 0")
+       assert.Equal(t, int64(0), stats.LastPublishTimestamp, 
"LastPublishTimestamp should be 0 initially")
+
+       // Publish a message
+       client, err := pulsar.NewClient(pulsar.ClientOptions{
+               URL: lookupURL,
+       })
+       assert.NoError(t, err)
+       defer client.Close()
+
+       producer, err := client.CreateProducer(pulsar.ProducerOptions{
+               Topic: topic,
+       })
+       assert.NoError(t, err)
+       defer producer.Close()
+
+       ctx := context.Background()
+       _, err = producer.Send(ctx, &pulsar.ProducerMessage{
+               Payload: []byte("test-message"),
+       })
+       assert.NoError(t, err)
+
+       // Wait for stats to update
+       assert.Eventually(t, func() bool {
+               s, err := admin.Topics().GetPartitionedStats(*topicName, true)
+               if err != nil {
+                       return false
+               }
+               // Partitioned stats LastPublishTimestamp is usually an 
aggregation or max of partitions
+               return s.LastPublishTimestamp > 0
+       }, 10*time.Second, 500*time.Millisecond, "LastPublishTimestamp should 
update after publishing")
+}

Review Comment:
   These two test functions (TestTopicStatsTimestamps and 
TestPartitionedTopicStatsTimestamps) have significant code duplication. 
Consider extracting the common test logic into a helper function that accepts a 
parameter to determine whether to test a regular or partitioned topic. This 
would reduce duplication, improve maintainability, and ensure both tests remain 
consistent. For example, create a helper like testStatsTimestamps(t *testing.T, 
partitions int) that both tests can call.



-- 
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