Conversation
|
Nice to see the connection/session split made explicit — One semantics question while this is still in progress: I think the idle clock may not restart when the last open stream is released.
That seems to conflict with the intent expressed in Ran this against bf508ca — it passes as written, i.e. the session is immediately evictable the moment the connection is released: Should the idle timeout start when the last open stream is released, rather than at the last client activity? Happy to help verify whichever semantics you settle on. |
| * keep-alive will be scheduled. | ||
| * @return this builder instance | ||
| */ | ||
| /** |
There was a problem hiding this comment.
Minor: the new sessionIdleTimeout javadoc landed between the existing keepAliveInterval javadoc and its method, so there are now two consecutive javadoc blocks and keepAliveInterval() is left undocumented.
|
@lxq19991111 there is a spec-compliant case where no SSE stream is ever established - the client only issues POST requests and the server sends Now should we indeed count disconnect as client activity? It can be a client initiated action, but in that case the client is likely signaling that it wants to disconnect, so I'm not sure it's worth keeping their session active for longer. |
|
That makes sense. Client-originated traffic is a better liveness signal than stream presence, especially for POST-only clients, and I agree a disconnect shouldn't by itself refresh session activity. My test shows the current behavior but doesn't establish that a fresh idle window should start on disconnect — thanks for clarifying. Separately, while tracing the cleanup paths I noticed an asymmetry between the GET and POST paths. This normally self-heals when the response pipeline terminates and runs My inclination would be to tie the cleanup to the session stream wrapper, since it owns the |
bf508ca to
dbde226
Compare
dbde226 to
6338039
Compare
|
I pulled the latest branch (c1cc11c) and re-ran the two session-level cases I raised earlier. The recent POST cleanup and disconnected-client changes work as expected: with a Mono.never() handler, the response stream now detaches from the session both when releaseTransport() is called and when the subscription is cancelled, and hasOpenStream() becomes false in both cases. Thanks for addressing that cleanup gap. The remaining limitation I see is narrower than the disconnected-client case covered by the latest commits: after releaseTransport(), the stream is detached and hasOpenStream() is false, but a thread waiting in responseStream.handle(...).block() remains parked because the handler subscription itself is still active. The PR already documents the general case where a never-completing handler can keep the doPost thread blocked, so I see this as a possible follow-up rather than a blocker for this PR. One possible approach would be to avoid the explicit wait for asynchronously completing handlers, subscribe with explicit terminal-error handling, retain the subscription in a race-safe holder, and dispose it when the existing AsyncListener reports the end of the async lifecycle. Cancellation could then reuse the cleanup already centralized in usingWhen. One semantic point to confirm would be how this should interact with pending server-initiated requests: cancellation calls closeGracefully(), while releaseTransport() keeps the session available for a separate POST. This would still not detect a silent peer disconnect when no further I/O occurs, especially with setTimeout(0), and it would not prevent a handler from blocking during subscription; those cases would require a separate timeout or processing-deadline policy. Would you be open to a focused follow-up PR for this narrower limitation, with regression coverage for the Mono.never() path, synchronous-completion races, and terminal write errors? |
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
- Sessions are marked active when a client makes a request - A session with an open stream is also considered active - Inactive sessions are removed at a regular interval Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
a2758eb to
8035337
Compare
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
Fixes #1021
Fixes #1022
Context
Streamable HTTP sessions and the connections they run on had no server-side lifecycle management, and expected the client to explicitly call
DELETEto remove the session.This lead to the session map growing infinitely (see #1022)
Additionally, the KeepAliveScheduler, when enabled, added pressure by sending frequent pings when no stream existed (#1021).
Implementation
This PR introduces fixes for various streams never being closed properly, as well as a session-sweeping mechanism which empties the session map when no activity is discovered.
Changes:
KeepAliveScheduler
GETSSE stream whenever a ping fails. The stream may later be re-established by the client.Session eviction
sessionSweepIntervalparameter (defaults to 30 minutes).POST.Session cleanup
Known limitations
doPost; the unblock depends on a write failing