Skip to content

[fix][client] Complete table view refresh after applying messages - #26566

Merged
merlimat merged 1 commit into
apache:masterfrom
lhotari:fix-tableview-refresh-apply
Sep 13, 2026
Merged

[fix][client] Complete table view refresh after applying messages#26566
merlimat merged 1 commit into
apache:masterfrom
lhotari:fix-tableview-refresh-apply

Conversation

@lhotari

@lhotari lhotari commented Sep 12, 2026

Copy link
Copy Markdown
Member

Motivation

TableView.refreshAsync() can complete while a received message is still being decoded, before its value has been applied to the table. The message position was published before the map update, allowing a concurrent refresh to treat that message as already applied. Callers that immediately read or scan the refreshed table can therefore see stale data.

Modifications

Publish the read position after updating the table and before notifying listeners. Skipped and keyless messages still advance the position. This preserves refresh calls from listeners while ensuring that refresh completion reflects the updated table.

Add a deterministic regression test that pauses message decoding, verifies that refresh remains pending, then releases decoding and checks the value and refreshes initiated by normal and skipped-message callbacks.

Verifying this change

  • Make sure that the change passes the CI checks.

  • The deterministic regression fails against the original implementation because refresh completes before message application.

  • Repeated both regression cases with temporary invocationCount=10: 20/20 passed, plus the existing client unit test.

  • Repeated the existing ownership-cleanup test ten times for each table-view implementation: 20/20 passed without changing its assertions or timeouts.

  • Final source, with temporary repetitions removed: all 8 selected tests passed, covering TableViewImplTest, ServiceUnitStateChannelTest.testCleanupDrainsAssignmentsAndRejectsNewOnes, and the existing TableViewTest refresh and reader-close cases.

  • ./gradlew spotlessCheck checkstyleMain checkstyleTest passed across all modules.

Tests ran with retries disabled. Local review checked refresh visibility and callback compatibility.

Does this pull request potentially affect one of the following parts:

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

Publish read positions only after applying or retaining the message value, while preserving refresh calls from update and skipped-message callbacks. Add deterministic coverage for refresh during decoding.
@merlimat
merlimat merged commit 172b7c3 into apache:master Sep 13, 2026
44 checks passed
@lhotari lhotari added this to the 5.0.0 milestone Sep 14, 2026
lhotari added a commit that referenced this pull request Sep 14, 2026
lhotari added a commit that referenced this pull request Sep 14, 2026
lhotari added a commit that referenced this pull request Sep 14, 2026
…ViewImplTest

The backport of #26566 (branch-4.0 commit 1450675, cherry-picked from
172b7c3 via branch-4.2 commit 078f7b2) added
testRefreshWaitsForMessageToBeApplied, which uses `var` and `List.of(...)`.
The pulsar-client module on branch-4.0 is compiled with
pulsar.client.compiler.release=8, so the test sources fail to compile
("cannot find symbol: class var", "method of()").

Replace `var` with explicit types and `List.of(...)` with
`Collections.emptyList()` / `Collections.singletonList(...)`. The test
logic is unchanged.

Validation: TableViewImplTest passes (3 tests, both data-provider variants).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants