Skip to content

feat(common): add deferred poll timeout support - #3948

Open
arunsingh wants to merge 2 commits into
apache:masterfrom
arunsingh:feat/poll-messages-wait-timeout-ng
Open

feat(common): add deferred poll timeout support#3948
arunsingh wants to merge 2 commits into
apache:masterfrom
arunsingh:feat/poll-messages-wait-timeout-ng

Conversation

@arunsingh

@arunsingh arunsingh commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR address?

Closes #3470

Rationale

PollMessages needs a backward-compatible way for clients to request a bounded wait when no messages are available. Immediate polling remains unchanged for existing clients and for a zero timeout.

What changed?

Empty PollMessages requests can now carry a trailing wait_timeout_us field; legacy requests decode it as zero, while partial trailing fields are rejected. The common, SDK, consumer-group, simulator, and HTTP-zero paths carry the value through the current tree.

This is a clean rebuild after closed PR #3605. The active core/server path currently rejects non-zero waits with typed FeatureUnavailable until a safe waiter/notifier implementation is designed. No core/server-ng, legacy server, benchmark markdown, or runbook files are included.

Local Execution

  • cargo fmt --all — passed
  • cargo clippy --all-targets --all-features -- -D warnings — passed
  • cargo test -p iggy_binary_protocol poll_messages — 15 passed
  • cargo test -p iggy_common wait_timeout — 2 passed
  • cargo check -p iggy -p server -p simulator — passed
  • cargo check -p integration --tests — passed
  • cargo machete — passed
  • cargo sort --workspace — passed; no changes needed
  • typos — passed
  • ./scripts/ci/license-headers.sh --check — passed with HawkEye 7
  • git diff --check — passed
  • Pre-commit hooks — not run; prek is not installed in this environment

cargo build --workspace was attempted but could not link in this x86_64-targeted macOS environment because the installed Homebrew xz and hwloc libraries are arm64. Full local cargo test is not claimed. Fresh GitHub CI run 32720521140 passed all 74 jobs after the rebase onto current master.

AI Usage

AI was used for code review, and test/CI orchestration. The changed code was reviewed and verified with the local checks above and GitHub CI; I can explain every line of the code if asked.

@arunsingh arunsingh changed the title Add deferred poll timeout support feat(common): add deferred poll timeout support Aug 21, 2026
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.61905% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.73%. Comparing base (a65f177) to head (d86e92b).
⚠️ Report is 45 commits behind head on master.

Files with missing lines Patch % Lines
core/common/src/traits/binary_impls/messages.rs 92.30% 2 Missing ⚠️
core/server/src/dispatch.rs 96.42% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3948      +/-   ##
============================================
- Coverage     83.93%   83.73%   -0.20%     
  Complexity     1358     1358              
============================================
  Files          1213     1214       +1     
  Lines        168441   168258     -183     
  Branches     135999   135941      -58     
============================================
- Hits         141373   140884     -489     
- Misses        23389    23557     +168     
- Partials       3679     3817     +138     
Components Coverage Δ
Rust Core 84.56% <97.61%> (-0.16%) ⬇️
Java SDK 66.67% <ø> (ø)
C# SDK 74.97% <ø> (-1.56%) ⬇️
Python SDK 90.13% <ø> (ø)
PHP SDK 84.48% <ø> (ø)
Node SDK 95.90% <ø> (ø)
Go SDK 68.29% <ø> (ø)
Files with missing lines Coverage Δ
...ry_protocol/src/requests/messages/poll_messages.rs 100.00% <100.00%> (ø)
core/common/src/traits/message_client.rs 100.00% <100.00%> (ø)
...e/sdk/src/client_wrappers/binary_message_client.rs 100.00% <100.00%> (ø)
core/sdk/src/clients/binary_message.rs 100.00% <100.00%> (ø)
core/server/src/http/wire.rs 95.08% <100.00%> (+0.01%) ⬆️
core/simulator/src/client.rs 65.96% <100.00%> (+0.07%) ⬆️
core/server/src/dispatch.rs 89.55% <96.42%> (+0.05%) ⬆️
core/common/src/traits/binary_impls/messages.rs 84.55% <92.30%> (+0.62%) ⬆️

... and 73 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.

Signed-off-by: Arun Singh <arunsingh.in@gmail.com>
Signed-off-by: Arun Singh <arunsingh.in@gmail.com>
@arunsingh
arunsingh force-pushed the feat/poll-messages-wait-timeout-ng branch from a4486d1 to d86e92b Compare August 24, 2026 11:10
@arunsingh
arunsingh marked this pull request as ready for review August 24, 2026 11:44
@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Aug 24, 2026
@arunsingh

Copy link
Copy Markdown
Contributor Author

Thanks, for reviewing earlier old PR #3605. I reopened this cleanly against current master and moved the implementation to the active core/server path. This is trailing PR to #3605, I kept the markdown/runbook artifact out of the new PR.

@hubcio hubcio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i dont see a point in merging this PR because there is no working path: every non-zero timeout is rejected by the server and by the SDK default impl, so this merges a public API and a wire field for a feature that does not exist. either put the waiter in this PR or cut it down to the protocol hunk and drop the trait method and the rejection test. Closes #3470 has to go either way - merging this would close the issue with nothing implemented. IggyConsumer still sleeps on poll_interval, so the high level consumer needs another pass even after the server side lands.

/// immediately available. A zero timeout preserves immediate polling.
/// Transports without deferred-poll support return `FeatureUnavailable`.
#[allow(clippy::too_many_arguments)]
async fn poll_messages_with_timeout(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

any non-zero timeout fails on every transport, so this is a public method with no working path. it also freezes the shape (8 positional args, Duration) before a server exists to validate it - hold the trait change until the wait lands.

strategy: polling_strategy_to_wire(strategy),
count,
auto_commit,
wait_timeout_us,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

group polls pick one assigned partition round-robin, so a wait here parks the consumer on that partition while the others may already have data. the group case needs a design answer before the field goes on the wire.

}

/// Reject a non-zero wait timeout until active-server deferred waits are implemented.
async fn reject_deferred_poll<B, MJ, S, SB>(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this is the whole server side: log and deny. the issue asks for the wait itself - port the #3605 waiter to this server instead of stubbing.

S: 'static,
SB: SuperblockStore + 'static,
{
if wire.wait_timeout_us != 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

dead check - handle_poll_messages already returned at line 2175 and the http wire hardcodes 0. drop it.

}

#[iggy_harness(test_client_transport = [Tcp])]
async fn given_non_zero_wait_timeout_when_polling_should_reject_feature_unavailable(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this pins the stub, not a behavior anyone wants. it goes away the day the wait lands - drop it, or make it the real wait test.

pos += 4;
let auto_commit = read_u8(buf, pos)? != 0;
pos += 1;
let wait_timeout_us = if buf.len() == pos {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

presence is sniffed from the remaining length, so the next optional field has to repeat the trick. a flags byte or a version would age better.

wait_timeout_us: u64,
}

fn duration_to_wait_timeout_us(wait_timeout: Duration) -> Result<u64, IggyError> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sub-microsecond timeouts truncate to 0 and silently become an immediate poll. round up or reject.

@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author PR is waiting on author response

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add deferred polling timeout to PollMessages

2 participants