Skip to content

fix(http2): emit server 'session' event promptly (before client 'connect')#5090

Merged
proggeramlug merged 1 commit into
mainfrom
fix/http2-server-session-prompt-emit
Jun 13, 2026
Merged

fix(http2): emit server 'session' event promptly (before client 'connect')#5090
proggeramlug merged 1 commit into
mainfrom
fix/http2-server-session-prompt-emit

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Problem

Perry deferred the http2 server 'session' event until after the in-process client's 'connect' event. This is causally wrong: an http2 server creates its session and sends its SETTINGS frame before a client can complete its connect handshake, so the server 'session' event must fire before the client 'connect'. Node on Linux does exactly this (server>client).

macOS node happens to defer it, and a prior Perry change was tuned to that macOS quirk, adding an explicit deferral mechanism that is incorrect for the canonical Linux sweep environment.

Fix

In crates/perry-ext-http-server/src/http2_server.rs process_pending_h2_events():

  • Flip the drain order so Session events are processed before ClientConnect (was the reverse).
  • Remove the local_server_session_ready() gate that re-queued the Session event behind the client's connect.
  • Delete the supporting machinery that existed only for that deferral: the H2_CLIENT_CONNECT_EMITTED thread-local, mark_client_connect_emitted(), and its call site.

Net: +7 / -64 lines, runtime emit-scheduling only — no new dispatch entries.

Verification

Target tests (run 3x, deterministic):

  • http2/session/sequential-session-cleanup.tsprobe order: server>client / probe settings cb: true 65535
  • http2/session/controls.tsserver controls: and server settings shape: now appear early (before ping return: true)

Note: these 2 tests will diff against local macOS node — that is the macOS-node quirk being corrected, not a regression. Judge by the causally-correct Linux server>client order.

No-regression: all other http/http2/https/net tests still match local node (43/44; the 1 fail, net/server/connection-state-limits.ts, is pre-existing — reproduced identically on pristine origin/main, unrelated getConnections timing in the untouched net path).

cargo test for perry-runtime/perry-stdlib/perry-codegen green (single-threaded; the parallel-run reds are unrelated global-state flakes — Date prototype / handle counters).

Summary by CodeRabbit

  • Refactor
    • Optimized HTTP/2 event processing logic by streamlining event ordering and removing unnecessary internal bookkeeping, resulting in improved efficiency.

…ect')

Perry deferred the http2 server 'session' event until after the in-process
client's 'connect' event, matching a macOS-node quirk. Causally the server
creates its session and sends its SETTINGS frame before a client can complete
its connect handshake, so 'session' must fire before 'connect' (Node on Linux:
server>client). Remove the deferral: drain Session events before ClientConnect
and delete the local_server_session_ready gate plus the H2_CLIENT_CONNECT_EMITTED
/mark_client_connect_emitted machinery that existed only to support it.
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

HTTP/2 event processing is simplified by removing per-session deferral bookkeeping and reordering event emission. Session events now sort before ClientConnect events, and deferral logic is eliminated, allowing events to emit based on global ordering and existing readiness checks.

Changes

HTTP/2 Event Ordering and Deferral Simplification

Layer / File(s) Summary
Remove deferral bookkeeping infrastructure
crates/perry-ext-http-server/src/http2_server.rs
Thread-local bookkeeping that tracked whether client connect was emitted, and the corresponding call that updated this state, are removed.
Implement new event ordering and remove deferral check
crates/perry-ext-http-server/src/http2_server.rs
process_pending_h2_events now sorts Session events before ClientConnect events. The conditional that deferred server session event emission until local readiness was met is removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 In Perry's streams, events now flow with grace,
Sessions leap ahead in the sorting race,
No more deferral's tangled thread,
Just simple ordering, as the rabbit said!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing HTTP/2 server session event emission to occur before client connect, matching the causal ordering.
Description check ✅ Passed The PR description comprehensively covers the problem, fix, and verification. It includes clear problem statement, specific changes made with file paths, test results, and explanations of expected behavior differences.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/http2-server-session-prompt-emit

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/perry-ext-http-server/src/http2_server.rs (1)

954-989: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't requeue ClientConnect based on server-session liveness after running session listeners.

With the new Session-first drain order, a server 'session' listener can synchronously call close()/destroy() on that session before Line 986 runs. At that point has_active_server_session() is false, so the same ClientConnect gets requeued forever and the client's 'connect' callback can be starved on every pump iteration.

Possible localized fix
 fn has_emitted_server_session(server_handle: i64) -> bool {
     let mut emitted = false;
     iter_handles_of::<Http2SessionHandle, _>(|session| {
-        if session.server_handle == server_handle
-            && session.session_event_emitted
-            && !session.closed
-            && !session.destroyed
-        {
+        if session.server_handle == server_handle && session.session_event_emitted {
             emitted = true;
         }
     });
     emitted
 }

 fn local_client_connect_ready(session_handle: i64) -> bool {
     let Some(server_handle) = local_server_handle_for_client(session_handle) else {
         return true;
     };
-    has_active_server_session(server_handle)
+    has_active_server_session(server_handle) || has_emitted_server_session(server_handle)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/perry-ext-http-server/src/http2_server.rs` around lines 954 - 989, The
ClientConnect requeue logic can starve the client if a preceding Session
listener synchronously closed the server session; update the ClientConnect
handling so it does not requeue purely because has_active_server_session() is
now false after running session listeners. Concretely: in the
Http2PendingEvent::ClientConnect branch, change the readiness check
(local_client_connect_ready(session_handle)) or its use so that if the
associated Http2SessionHandle has session_event_emitted == true (set earlier in
the Http2PendingEvent::Session branch) you proceed with the connect instead of
calling push_h2_event and continuing; alternatively, make
local_client_connect_ready consult session_event_emitted (or skip
has_active_server_session) so a client connect won't be requeued forever. Ensure
the code still requeues only for truly not-yet-ready sessions and keep
push_h2_event as the fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/perry-ext-http-server/src/http2_server.rs`:
- Around line 954-989: The ClientConnect requeue logic can starve the client if
a preceding Session listener synchronously closed the server session; update the
ClientConnect handling so it does not requeue purely because
has_active_server_session() is now false after running session listeners.
Concretely: in the Http2PendingEvent::ClientConnect branch, change the readiness
check (local_client_connect_ready(session_handle)) or its use so that if the
associated Http2SessionHandle has session_event_emitted == true (set earlier in
the Http2PendingEvent::Session branch) you proceed with the connect instead of
calling push_h2_event and continuing; alternatively, make
local_client_connect_ready consult session_event_emitted (or skip
has_active_server_session) so a client connect won't be requeued forever. Ensure
the code still requeues only for truly not-yet-ready sessions and keep
push_h2_event as the fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 75284f74-5336-4dbf-9c7b-2e461136b691

📥 Commits

Reviewing files that changed from the base of the PR and between 9b6bbe0 and 6035723.

📒 Files selected for processing (1)
  • crates/perry-ext-http-server/src/http2_server.rs

@proggeramlug proggeramlug merged commit f01ed03 into main Jun 13, 2026
13 of 14 checks passed
@proggeramlug proggeramlug deleted the fix/http2-server-session-prompt-emit branch June 13, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant