Skip to content

refactor(transport): extract shared stream state handling logic in loopyWriter.processData()#9125

Open
Exgene wants to merge 2 commits into
grpc:masterfrom
Exgene:refactor/#9117-dedupe-data-frame-handling
Open

refactor(transport): extract shared stream state handling logic in loopyWriter.processData()#9125
Exgene wants to merge 2 commits into
grpc:masterfrom
Exgene:refactor/#9117-dedupe-data-frame-handling

Conversation

@Exgene
Copy link
Copy Markdown

@Exgene Exgene commented May 13, 2026

Fixes: #9117

Refactors the duplicated post write stream state handling in loopyWriter.processData() present in internal/transport/controlbuf.go into a shared helper l.updateStreamAfterWrite(). Both empty and non empty DATA frame paths now share the same stream state handling logic.

This change also adds the stream quota check (int(l.oiws) - str.bytesOutStanding) to the empty frame path. This is safe because empty DATA frames send 0 bytes, so bytesOutStanding doesn't change.

RELEASE NOTES: n/a

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented May 13, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: Exgene / name: Kausthubh J Rao (dd7c7b5)

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 72.72727% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.13%. Comparing base (7c47d2a) to head (dd7c7b5).
⚠️ Report is 3 commits behind head on master.

Files with missing lines Patch % Lines
internal/transport/controlbuf.go 72.72% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9125      +/-   ##
==========================================
- Coverage   83.21%   83.13%   -0.08%     
==========================================
  Files         413      413              
  Lines       33482    33479       -3     
==========================================
- Hits        27863    27834      -29     
- Misses       4212     4224      +12     
- Partials     1407     1421      +14     
Files with missing lines Coverage Δ
internal/transport/controlbuf.go 91.17% <72.72%> (+1.61%) ⬆️

... and 24 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Exgene
Copy link
Copy Markdown
Author

Exgene commented May 13, 2026

how do i add labels? i can't really add it from my side on the sidebar, and it wasn't present in the contributing guidelines either.

@Exgene Exgene changed the title refactor(transport): deduplicate data frame handling refactor(transport): extract shared stream state handling logic in loopyWriter.processData() May 14, 2026
@easwars easwars added the Type: Internal Cleanup Refactors, etc label May 20, 2026
@easwars easwars added this to the 1.82 Release milestone May 20, 2026
@easwars easwars requested a review from arjan-bal May 20, 2026 04:34
@easwars
Copy link
Copy Markdown
Contributor

easwars commented May 20, 2026

@arjan-bal : Could you please take a look at this one? Thanks.

@arjan-bal
Copy link
Copy Markdown
Contributor

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the processData method in internal/transport/controlbuf.go by extracting duplicated stream update logic into a new helper method called updateStreamAfterWrite. This helper method now centralizes the logic for updating stream states, handling trailers, and re-enqueuing active streams after a write operation. I have no feedback to provide as there were no review comments to evaluate.

arjan-bal
arjan-bal previously approved these changes May 21, 2026
Copy link
Copy Markdown
Contributor

@arjan-bal arjan-bal left a comment

Choose a reason for hiding this comment

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

Some minor comments, otherwise LGTM. Please address them before I add a second reviewer.

Comment thread internal/transport/controlbuf.go Outdated
Comment on lines 966 to 968
if err := l.updateStreamAfterWrite(str); err != nil {
return false, err
}
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.

nit: Can be simplified as return false, l.updateStreamAfterWrite(str). Same for the updateStreamAfterWrite below.

}
} else if int(l.oiws)-str.bytesOutStanding <= 0 { // Ran out of stream quota.
str.state = waitingOnStreamQuota
} else { // Otherwise add it back to the list of active streams.
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.

Can you please leave the comment here?

@arjan-bal arjan-bal assigned Exgene and unassigned arjan-bal May 21, 2026
@Exgene
Copy link
Copy Markdown
Author

Exgene commented May 21, 2026

happy to add them!

Comment thread internal/transport/controlbuf.go Outdated
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.

Is suspect we can remove this special handing of empty data frames if we just modify the following check below to not return early:

if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control.
str.state = waitingOnStreamQuota
return false, nil
} else if maxSize > strQuota {

It should be something similar to:

isEmpty := len(dataItem.h) == 0 && reader.Remaining() == 0
if strQuota <= 0 && !isEmpty {
    // return early
}

Can you check if this is possible?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

sure let me check that

@arjan-bal arjan-bal self-requested a review May 22, 2026 06:34
@arjan-bal arjan-bal dismissed their stale review May 22, 2026 06:35

Exploring further simplification.

@arjan-bal
Copy link
Copy Markdown
Contributor

happy to add them!

To clarify, I'll add the second reviewer after you've addressed the pending comments.

@Exgene
Copy link
Copy Markdown
Author

Exgene commented May 22, 2026

@arjan-bal I have refactored it accordingly, I think there is this one case where the frame is empty and the value of strQuota could become negative? hence i clamped it with max(strQuota, 0).

I also refactored

else if maxSize > strQuota {
        maxSize = strQuota
}

with simpler

maxSize = min(maxSize, int(l.sendQuota)) 

And finally in the empty frame case should onEachWrite() run? i have gated that as well for now.

@Exgene
Copy link
Copy Markdown
Author

Exgene commented May 22, 2026

Also not sure why that test case is failing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove duplication of code in loopyWriter.ProcessData

3 participants