Skip to content

Conversation

@codelipenghui
Copy link
Contributor

Motivation

When topics are idle (no recent write activity), stats collection needs to read from storage to get the last publish timestamp since the managed ledger doesn't cache it. If stats are polled frequently, this causes unnecessary repeated storage reads for the same value.

Modifications

  • Added cachedLastPublishTimestamp field to cache the last publish timestamp for idle topics
  • The cache is only used when ledger.getLastAddEntryTime() <= 0 (topic is idle)
  • When the topic has recent activity (ledger.getLastAddEntryTime() > 0), we use the ledger's value directly and clear the cache
  • This optimization specifically targets idle topics where stats are polled repeatedly but nothing is being written
  • Added comprehensive unit test to verify the caching behavior

Verifying this change

  • Added unit test testLastPublishTimestampCaching that verifies:
    1. First stats call on idle topic reads from storage and caches
    2. Second stats call uses cached value (no storage read)
    3. When topic becomes active, uses ledger value and clears cache
    4. When topic becomes idle again, reads from storage (cache was properly cleared)

Documentation

  • doc-required (Your PR needs to update docs and you will update later)
  • doc-not-needed (Please explain why)
    • This is an internal optimization that doesn't change any public APIs or user-facing behavior
  • doc (Your PR contains doc changes)
  • doc-complete (Docs have been already added)

🤖 Generated with Claude Code

…uce storage reads

### Motivation

When topics are idle (no recent write activity), stats collection needs to read from storage to get the last publish timestamp since the managed ledger doesn't cache it. If stats are polled frequently, this causes unnecessary repeated storage reads for the same value.

### Modifications

- Added cachedLastPublishTimestamp field to cache the last publish timestamp for idle topics
- The cache is only used when ledger.getLastAddEntryTime() <= 0 (topic is idle)
- When the topic has recent activity (ledger.getLastAddEntryTime() > 0), we use the ledger's value directly and clear the cache
- This optimization specifically targets idle topics where stats are polled repeatedly but nothing is being written

### Verifying this change

- Added unit test testLastPublishTimestampCaching that verifies:
  1. First stats call on idle topic reads from storage and caches
  2. Second stats call uses cached value (no storage read)
  3. When topic becomes active, uses ledger value and clears cache
  4. When topic becomes idle again, reads from storage (cache was properly cleared)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions bot added the doc-not-needed Your PR changes do not impact docs label Oct 7, 2025
@codelipenghui codelipenghui self-assigned this Oct 7, 2025
@codelipenghui codelipenghui added this to the 4.2.0 milestone Oct 7, 2025
@codelipenghui codelipenghui added release/4.1.2 ready-to-test type/enhancement The enhancements for the existing features or docs. e.g. reduce memory usage of the delayed messages labels Oct 7, 2025
@codelipenghui codelipenghui requested a review from lhotari October 7, 2025 18:34
@codelipenghui codelipenghui assigned hangc0276 and unassigned hangc0276 Oct 7, 2025
@codecov-commenter
Copy link

codecov-commenter commented Oct 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.29%. Comparing base (7d35d7c) to head (c6bc855).
⚠️ Report is 28 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##             master   #24825      +/-   ##
============================================
- Coverage     74.33%   74.29%   -0.04%     
+ Complexity    33438    33423      -15     
============================================
  Files          1912     1912              
  Lines        149077   149100      +23     
  Branches      17300    17301       +1     
============================================
- Hits         110815   110777      -38     
- Misses        29442    29501      +59     
- Partials       8820     8822       +2     
Flag Coverage Δ
inttests 26.38% <84.61%> (-0.10%) ⬇️
systests 22.79% <84.61%> (+0.05%) ⬆️
unittests 73.79% <100.00%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...sar/broker/service/persistent/PersistentTopic.java 79.14% <100.00%> (+0.16%) ⬆️

... and 82 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@lhotari lhotari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lhotari
Copy link
Member

lhotari commented Oct 8, 2025

@codelipenghui There's a failing test, AdminApi2Test.testTopicCreationAndLastPublishTimestamps

  Warning:  Tests run: 280, Failures: 0, Errors: 0, Skipped: 194, Time elapsed: 759.3 s -- in org.apache.pulsar.broker.admin.TopicPoliciesTest
  Error:  Tests run: 142, Failures: 1, Errors: 0, Skipped: 49, Time elapsed: 814.1 s <<< FAILURE! -- in org.apache.pulsar.broker.admin.AdminApi2Test
  Error:  org.apache.pulsar.broker.admin.AdminApi2Test.testTopicCreationAndLastPublishTimestamps -- Time elapsed: 2.343 s <<< FAILURE!
  java.lang.AssertionError: expected [0] but found [1759894074476]
  	at org.testng.Assert.fail(Assert.java:110)
  	at org.testng.Assert.failNotEquals(Assert.java:1577)
  	at org.testng.Assert.assertEqualsImpl(Assert.java:149)
  	at org.testng.Assert.assertEquals(Assert.java:131)
  	at org.testng.Assert.assertEquals(Assert.java:979)
  	at org.testng.Assert.assertEquals(Assert.java:955)
  	at org.testng.Assert.assertEquals(Assert.java:989)
  	at org.apache.pulsar.broker.admin.AdminApi2Test.testTopicCreationAndLastPublishTimestamps(AdminApi2Test.java:4191)
  	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
  	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
  	at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
  	at org.testng.internal.invokers.InvokeMethodRunnable.runOne(InvokeMethodRunnable.java:47)
  	at org.testng.internal.invokers.InvokeMethodRunnable.call(InvokeMethodRunnable.java:76)
  	at org.testng.internal.invokers.InvokeMethodRunnable.call(InvokeMethodRunnable.java:11)
  	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
  	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
  	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
  	at java.base/java.lang.Thread.run(Thread.java:1583)

@codelipenghui codelipenghui merged commit d5e1d7e into apache:master Oct 9, 2025
96 of 98 checks passed
@codelipenghui codelipenghui deleted the fix/cache-last-publish-timestamp-for-idle-topics branch October 9, 2025 03:10
codelipenghui added a commit that referenced this pull request Oct 9, 2025
@codelipenghui
Copy link
Contributor Author

Cherry-picked to branch-4.1, and there is no need to cherry-pick to branch-4.0 since the issue is only for 4.1.0

codelipenghui added a commit that referenced this pull request Dec 9, 2025
codelipenghui added a commit that referenced this pull request Dec 9, 2025
ganesh-ctds pushed a commit to datastax/pulsar that referenced this pull request Dec 19, 2025
…uce storage reads (apache#24825)

(cherry picked from commit d5e1d7e)
(cherry picked from commit f0c9b05)
ganesh-ctds pushed a commit to datastax/pulsar that referenced this pull request Dec 19, 2025
ganesh-ctds pushed a commit to datastax/pulsar that referenced this pull request Dec 19, 2025
…uce storage reads (apache#24825)

(cherry picked from commit d5e1d7e)
(cherry picked from commit f0c9b05)
ganesh-ctds pushed a commit to datastax/pulsar that referenced this pull request Dec 19, 2025
ganesh-ctds pushed a commit to datastax/pulsar that referenced this pull request Dec 19, 2025
…uce storage reads (apache#24825)

(cherry picked from commit d5e1d7e)
(cherry picked from commit f0c9b05)
ganesh-ctds pushed a commit to datastax/pulsar that referenced this pull request Dec 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-picked/branch-4.0 cherry-picked/branch-4.1 doc-not-needed Your PR changes do not impact docs ready-to-test release/4.0.9 release/4.1.2 type/enhancement The enhancements for the existing features or docs. e.g. reduce memory usage of the delayed messages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants