Skip to content

[grid] Skip the TCP tunnel read-idle close when reads are paused#17578

Merged
shs96c merged 1 commit into
SeleniumHQ:trunkfrom
shs96c:grid-tunnel-idle-backpressure
May 28, 2026
Merged

[grid] Skip the TCP tunnel read-idle close when reads are paused#17578
shs96c merged 1 commit into
SeleniumHQ:trunkfrom
shs96c:grid-tunnel-idle-backpressure

Conversation

@shs96c
Copy link
Copy Markdown
Member

@shs96c shs96c commented May 27, 2026

The read-idle close that TcpUpgradeTunnelHandler installs after the tunnel is established (introduced by #17197) tears down both tunnel channels when no bytes have been received for 120 seconds. That is the right behaviour when an intermediate load balancer has silently dropped the TCP connection, but it interacts badly with the backpressure mirroring added in #17543: when the peer's outbound buffer crosses its high-water mark, TcpTunnelHandler sets autoRead=false on this side, no channelRead events fire, and the read-idle timer reaches its threshold even though the stall is by design. A sustained slow consumer for more than two minutes will therefore have the tunnel torn down underneath it.

Gate the close in IdleCloseHandler.userEventTriggered on the channel's autoRead flag: while reads are paused by backpressure, log at FINE and ignore the event. As soon as the peer drains and TcpTunnelHandler restores autoRead=true the read-idle clock starts again from a fresh read, so a legitimately dropped connection is still detected within the same window once traffic resumes.

IdleCloseHandler is promoted from a private nested class to package-private so a focused EmbeddedChannel unit test can exercise both branches: the close-both-channels behaviour on a normal idle event, and the ignored-while-paused behaviour with autoRead=false.

🤖 Generated with Claude Code

@selenium-ci selenium-ci added B-grid Everything grid and server related C-java Java Bindings B-build Includes scripting, bazel and CI integrations labels May 27, 2026
@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Apply WebSocket frame fast path on Node and fix backpressure-induced tunnel teardown

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Apply WebSocket frame fast path on Node side, bypassing Message layer
• Buffer pre-handshake frames and drain on upgrade completion
• Skip TCP tunnel read-idle close when backpressure pauses reads
• Safely truncate WebSocket close-frame reasons to RFC 6455 limit
Diagram
flowchart LR
  A["Node WebSocket<br/>Upgrade"] -->|"install<br/>WebSocketFrameProxy"| B["Direct Frame<br/>Forwarding"]
  B -->|"bypass Message<br/>layer"| C["Reduced Allocation<br/>& Executor Hops"]
  D["Pre-handshake<br/>Frames"] -->|"buffer in<br/>arrival order"| E["Drain on<br/>onUpgrade"]
  F["Read-idle Event"] -->|"check autoRead<br/>flag"| G{"Backpressure<br/>Active?"}
  G -->|"yes"| H["Log & Ignore"]
  G -->|"no"| I["Close Tunnel"]
  J["Close Reason"] -->|"truncate safely<br/>at char boundary"| K["RFC 6455<br/>Compliant"]

Loading

Grey Divider

File Changes

1. java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java ✨ Enhancement +281/-93

Implement direct frame forwarding with pre-handshake buffering

java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java


2. java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java ✨ Enhancement +5/-2

Add safe close-reason truncation to Router listener

java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java


3. java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java 🐞 Bug fix +13/-1

Skip read-idle close when backpressure pauses reads

java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java


View more (7)
4. java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java ✨ Enhancement +32/-0

Add RFC 6455 compliant close-reason truncation utility

java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java


5. java/test/org/openqa/selenium/grid/node/NodeDirectForwardingListenerTest.java 🧪 Tests +298/-0

New test for DirectForwardingListener frame buffering and overflow

java/test/org/openqa/selenium/grid/node/NodeDirectForwardingListenerTest.java


6. java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java 🧪 Tests +57/-0

New test for idle close handler backpressure behavior

java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java


7. java/test/org/openqa/selenium/netty/server/WebSocketFrameProxyTest.java 🧪 Tests +25/-0

Add tests for close-reason truncation with multi-byte UTF-8

java/test/org/openqa/selenium/netty/server/WebSocketFrameProxyTest.java


8. java/src/org/openqa/selenium/grid/node/BUILD.bazel Dependencies +4/-0

Add Netty dependencies for frame forwarding

java/src/org/openqa/selenium/grid/node/BUILD.bazel


9. java/test/org/openqa/selenium/grid/node/BUILD.bazel Dependencies +2/-0

Add Netty test dependencies for DirectForwardingListener tests

java/test/org/openqa/selenium/grid/node/BUILD.bazel


10. java/test/org/openqa/selenium/netty/server/BUILD.bazel Dependencies +2/-0

Add IdleCloseHandlerTest and netty-handler dependency

java/test/org/openqa/selenium/netty/server/BUILD.bazel


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 27, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2)

Grey Divider


Remediation recommended

1. IdleCloseHandlerTest constructs IdleStateEvent 📘 Rule violation ≡ Correctness
Description
The new unit test manually instantiates IdleStateEvent, which may be non-public in Netty (and
therefore fail to compile/run), undermining the intent of adding a small, reliable unit test for
this change.
Code

java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java[52]

Evidence
PR Compliance ID 5 requires feasible changes to be covered by small/unit tests; a unit test that may
not compile or execute reliably (due to instantiating a Netty event type that is commonly not
publicly constructible) fails to meet that objective. The added line uses new IdleStateEvent(...)
rather than the Netty-provided constants used elsewhere in the same test file.

AGENTS.md: Prefer tests-first and favor small/unit tests over browser tests; avoid mocks
java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java[41-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`IdleCloseHandlerTest` creates `new IdleStateEvent(IdleState.READER_IDLE, true)`. In Netty this constructor is typically not publicly accessible, so the test may fail to compile/run.

## Issue Context
The repository pins Netty `4.2.13.Final`, and Netty provides `IdleStateEvent` singleton constants (e.g., `READER_IDLE_STATE_EVENT`, `FIRST_READER_IDLE_STATE_EVENT`) specifically to avoid direct construction.

## Fix Focus Areas
- java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java[41-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Idle-close disabled during pause 🐞 Bug ☼ Reliability
Description
TcpUpgradeTunnelHandler.IdleCloseHandler now returns on every IdleStateEvent when autoRead is false,
so read-idle timeouts cannot close a tunnel leg while backpressure has paused reads. Because
TcpTunnelHandler mirrors outbound backpressure by flipping the peer channel’s autoRead flag, a
prolonged stall can keep a dropped/blackholed connection from being detected via the read-idle close
until reads resume.
Code

java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java[R392-404]

Evidence
The idle-close handler now explicitly returns without closing when autoRead is disabled. Since
TcpTunnelHandler actively disables the peer’s autoRead when the local outbound buffer becomes
non-writable, backpressure can place the channel in exactly the state where idle-close is
suppressed.

java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java[372-415]
java/src/org/openqa/selenium/netty/server/TcpTunnelHandler.java[65-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`IdleCloseHandler` currently ignores *all* read-idle events while `autoRead=false`. This avoids false-positive tunnel teardown under backpressure, but it also removes the only protection against silently dropped/blackholed TCP connections during extended stalls.

### Issue Context
Backpressure mirroring is implemented by `TcpTunnelHandler.channelWritabilityChanged()` via `target.config().setAutoRead(ctx.channel().isWritable())`, so a stalled outbound buffer can keep the peer leg’s reads paused for extended periods.

### Fix Focus Areas
- java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java[390-414]
- java/src/org/openqa/selenium/netty/server/TcpTunnelHandler.java[65-75]

### What to change
Implement a bounded-stall policy so that *some* cleanup still happens if reads remain paused for too long, for example:
- Track when `autoRead` first became `false` (or track consecutive ignored idle events) and still close both channels after a longer cap (e.g., N× the idle window), or
- Only skip the close when `autoRead=false` **and** the tunnel is making forward progress (e.g., peer becomes writable / queued bytes drain); otherwise allow idle-close.

This keeps the slow-consumer/backpressure fix while preventing indefinite retention during pathological stalls.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Stacked WebSocket refactor included 📘 Rule violation ⚙ Maintainability
Description
The PR includes substantial WebSocket proxy refactoring and new utility behavior in addition to the
stated TCP tunnel idle-close gating, increasing blast radius and making rollback/review harder. This
conflicts with the requirement to keep diffs narrowly scoped to the minimal necessary change.
Code

java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[R268-589]

Evidence
PR Compliance ID 3 requires keeping diffs small and avoiding unrelated churn. The diff shows a large
refactor in ProxyNodeWebsockets (new FrameProxyConsumer/DirectForwardingListener and pipeline
rewiring) plus additional shared behavior (WebSocketFrameProxy.truncateCloseReason) and related
routing changes, which go beyond the narrow TCP tunnel idle-close gating.

AGENTS.md: Avoid repo-wide refactors or formatting-only churn; keep diffs small and reversible
java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[268-589]
java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[175-201]
java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java[335-355]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
This PR contains a large, stacked set of WebSocket proxy changes in addition to the TCP tunnel idle-close/backpressure fix, which increases review burden and rollback risk.

## Issue Context
Compliance requires avoiding broad refactors/formatting churn unrelated to the specific functional change. The current diff touches multiple components (node websocket proxying, router websocket close handling, and shared Netty helper utilities) beyond the tunnel idle-close adjustment.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[268-589]
- java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[175-201]
- java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java[335-355]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Unbounded close-reason encoding 🐞 Bug ➹ Performance
Description
WebSocketFrameProxy.truncateCloseReason uses reason.getBytes(UTF_8) to measure length, allocating a
byte[] proportional to the full reason even though the returned close reason is capped at 123 bytes.
If an upstream component supplies an unexpectedly large close reason, this can cause avoidable
allocation/GC pressure on the close path.
Code

java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[R191-194]

Evidence
The helper currently allocates a full UTF-8 byte[] to test length, and it is invoked with the
upstream-provided close reason in both the Node and Router direct-forwarding listeners.

java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[187-201]
java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[521-548]
java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java[332-358]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`WebSocketFrameProxy.truncateCloseReason` measures UTF-8 length via `reason.getBytes(UTF_8).length`, which allocates a full byte array for the entire input string. Since the method’s purpose is to cap output at 123 bytes, the length check can be implemented using a bounded `CharsetEncoder` pass (no large allocations), while still guaranteeing no UTF-8 sequence is split.

### Issue Context
This helper is called from WebSocket proxy listeners on upstream close events, so the `reason` string is not inherently bounded by this method.

### Fix Focus Areas
- java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[187-201]

### Suggested fix
Replace the `getBytes` fast-path with a bounded encoder check:
- Encode into a 123-byte `ByteBuffer` using `CharsetEncoder.encode(...)`.
 - If the result is **UNDERFLOW**, the reason fits: return the original string.
 - If the result is **OVERFLOW**, perform the existing truncation approach (encode into 120 bytes, decode, append `...`).
This keeps behavior identical for valid short reasons while avoiding allocating `O(n)` bytes for long inputs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit b2cf8a9

Results up to commit a7188f9


🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0)


Remediation recommended
1. Stacked WebSocket refactor included 📘 Rule violation ⚙ Maintainability
Description
The PR includes substantial WebSocket proxy refactoring and new utility behavior in addition to the
stated TCP tunnel idle-close gating, increasing blast radius and making rollback/review harder. This
conflicts with the requirement to keep diffs narrowly scoped to the minimal necessary change.
Code

java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[R268-589]

Evidence
PR Compliance ID 3 requires keeping diffs small and avoiding unrelated churn. The diff shows a large
refactor in ProxyNodeWebsockets (new FrameProxyConsumer/DirectForwardingListener and pipeline
rewiring) plus additional shared behavior (WebSocketFrameProxy.truncateCloseReason) and related
routing changes, which go beyond the narrow TCP tunnel idle-close gating.

AGENTS.md: Avoid repo-wide refactors or formatting-only churn; keep diffs small and reversible
java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[268-589]
java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[175-201]
java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java[335-355]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
This PR contains a large, stacked set of WebSocket proxy changes in addition to the TCP tunnel idle-close/backpressure fix, which increases review burden and rollback risk.

## Issue Context
Compliance requires avoiding broad refactors/formatting churn unrelated to the specific functional change. The current diff touches multiple components (node websocket proxying, router websocket close handling, and shared Netty helper utilities) beyond the tunnel idle-close adjustment.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[268-589]
- java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[175-201]
- java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java[335-355]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unbounded close-reason encoding 🐞 Bug ➹ Performance
Description
WebSocketFrameProxy.truncateCloseReason uses reason.getBytes(UTF_8) to measure length, allocating a
byte[] proportional to the full reason even though the returned close reason is capped at 123 bytes.
If an upstream component supplies an unexpectedly large close reason, this can cause avoidable
allocation/GC pressure on the close path.
Code

java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[R191-194]

Evidence
The helper currently allocates a full UTF-8 byte[] to test length, and it is invoked with the
upstream-provided close reason in both the Node and Router direct-forwarding listeners.

java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[187-201]
java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java[521-548]
java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java[332-358]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`WebSocketFrameProxy.truncateCloseReason` measures UTF-8 length via `reason.getBytes(UTF_8).length`, which allocates a full byte array for the entire input string. Since the method’s purpose is to cap output at 123 bytes, the length check can be implemented using a bounded `CharsetEncoder` pass (no large allocations), while still guaranteeing no UTF-8 sequence is split.

### Issue Context
This helper is called from WebSocket proxy listeners on upstream close events, so the `reason` string is not inherently bounded by this method.

### Fix Focus Areas
- java/src/org/openqa/selenium/netty/server/WebSocketFrameProxy.java[187-201]

### Suggested fix
Replace the `getBytes` fast-path with a bounded encoder check:
- Encode into a 123-byte `ByteBuffer` using `CharsetEncoder.encode(...)`.
 - If the result is **UNDERFLOW**, the reason fits: return the original string.
 - If the result is **OVERFLOW**, perform the existing truncation approach (encode into 120 bytes, decode, append `...`).
This keeps behavior identical for valid short reasons while avoiding allocating `O(n)` bytes for long inputs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit a525a9c


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0)


Remediation recommended
1. Idle-close disabled during pause 🐞 Bug ☼ Reliability
Description
TcpUpgradeTunnelHandler.IdleCloseHandler now returns on every IdleStateEvent when autoRead is false,
so read-idle timeouts cannot close a tunnel leg while backpressure has paused reads. Because
TcpTunnelHandler mirrors outbound backpressure by flipping the peer channel’s autoRead flag, a
prolonged stall can keep a dropped/blackholed connection from being detected via the read-idle close
until reads resume.
Code

java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java[R392-404]

Evidence
The idle-close handler now explicitly returns without closing when autoRead is disabled. Since
TcpTunnelHandler actively disables the peer’s autoRead when the local outbound buffer becomes
non-writable, backpressure can place the channel in exactly the state where idle-close is
suppressed.

java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java[372-415]
java/src/org/openqa/selenium/netty/server/TcpTunnelHandler.java[65-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`IdleCloseHandler` currently ignores *all* read-idle events while `autoRead=false`. This avoids false-positive tunnel teardown under backpressure, but it also removes the only protection against silently dropped/blackholed TCP connections during extended stalls.

### Issue Context
Backpressure mirroring is implemented by `TcpTunnelHandler.channelWritabilityChanged()` via `target.config().setAutoRead(ctx.channel().isWritable())`, so a stalled outbound buffer can keep the peer leg’s reads paused for extended periods.

### Fix Focus Areas
- java/src/org/openqa/selenium/netty/server/TcpUpgradeTunnelHandler.java[390-414]
- java/src/org/openqa/selenium/netty/server/TcpTunnelHandler.java[65-75]

### What to change
Implement a bounded-stall policy so that *some* cleanup still happens if reads remain paused for too long, for example:
- Track when `autoRead` first became `false` (or track consecutive ignored idle events) and still close both channels after a longer cap (e.g., N× the idle window), or
- Only skip the close when `autoRead=false` **and** the tunnel is making forward progress (e.g., peer becomes writable / queued bytes drain); otherwise allow idle-close.

This keeps the slow-consumer/backpressure fix while preventing indefinite retention during pathological stalls.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit ae83518


🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0)


Remediation recommended
1. IdleCloseHandlerTest constructs IdleStateEvent 📘 Rule violation ≡ Correctness
Description
The new unit test manually instantiates IdleStateEvent, which may be non-public in Netty (and
therefore fail to compile/run), undermining the intent of adding a small, reliable unit test for
this change.
Code

java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java[52]

Evidence
PR Compliance ID 5 requires feasible changes to be covered by small/unit tests; a unit test that may
not compile or execute reliably (due to instantiating a Netty event type that is commonly not
publicly constructible) fails to meet that objective. The added line uses new IdleStateEvent(...)
rather than the Netty-provided constants used elsewhere in the same test file.

AGENTS.md: Prefer tests-first and favor small/unit tests over browser tests; avoid mocks
java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java[41-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`IdleCloseHandlerTest` creates `new IdleStateEvent(IdleState.READER_IDLE, true)`. In Netty this constructor is typically not publicly accessible, so the test may fail to compile/run.

## Issue Context
The repository pins Netty `4.2.13.Final`, and Netty provides `IdleStateEvent` singleton constants (e.g., `READER_IDLE_STATE_EVENT`, `FIRST_READER_IDLE_STATE_EVENT`) specifically to avoid direct construction.

## Fix Focus Areas
- java/test/org/openqa/selenium/netty/server/IdleCloseHandlerTest.java[41-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

@shs96c shs96c force-pushed the grid-tunnel-idle-backpressure branch from a7188f9 to a525a9c Compare May 27, 2026 15:15
@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 27, 2026

Code review by qodo was updated up to the latest commit a525a9c

@shs96c shs96c force-pushed the grid-tunnel-idle-backpressure branch from a525a9c to ae83518 Compare May 27, 2026 17:20
@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 27, 2026

Code review by qodo was updated up to the latest commit ae83518

The read-idle close that TcpUpgradeTunnelHandler installs after the
tunnel is established (introduced by db9b07a, 2026-03-11,
"[grid] Router WebSocket handle dropped close frames, idle disconnects,
high-latency proxying", SeleniumHQ#17197) tears down both tunnel channels when no
bytes have been received for 120 seconds. That is the right behaviour
when an intermediate load balancer has silently dropped the TCP
connection, but it interacts badly with the backpressure mirroring
added in 5cf2e2a (2026-05-26, "[grid] Apply TCP backpressure across
the WebSocket tunnel handler", SeleniumHQ#17543): when the peer's outbound buffer
crosses its high-water mark, TcpTunnelHandler sets autoRead=false on
this side, no channelRead events fire, and the read-idle timer reaches
its threshold even though the stall is by design. A sustained slow
consumer for more than two minutes will therefore have the tunnel torn
down underneath it.

Gate the close in IdleCloseHandler.userEventTriggered on the channel's
autoRead flag: while reads are paused by backpressure, log at FINE and
ignore the event. As soon as the peer drains and TcpTunnelHandler
restores autoRead=true the read-idle clock starts again from a fresh
read, so a legitimately dropped connection is still detected within
the same window once traffic resumes.

IdleCloseHandler is promoted from a private nested class to
package-private so a focused EmbeddedChannel unit test can exercise
both branches: the close-both-channels behaviour on a normal idle
event, and the ignored-while-paused behaviour with autoRead=false.
@shs96c shs96c force-pushed the grid-tunnel-idle-backpressure branch from ae83518 to b2cf8a9 Compare May 28, 2026 09:27
@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 28, 2026

Code review by qodo was updated up to the latest commit b2cf8a9

@shs96c shs96c merged commit 62f911a into SeleniumHQ:trunk May 28, 2026
45 of 46 checks passed
@shs96c shs96c deleted the grid-tunnel-idle-backpressure branch May 28, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-build Includes scripting, bazel and CI integrations B-grid Everything grid and server related C-java Java Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants