Make session-sweeping non-blocking
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
This commit is contained in:
parent
9948eecbb7
commit
caafc85575
1 changed files with 21 additions and 26 deletions
|
|
@ -216,17 +216,14 @@ public class HttpServletStreamableServerTransportProvider extends HttpServlet
|
||||||
* down
|
* down
|
||||||
*/
|
*/
|
||||||
private Disposable startSessionSweeper(Duration sessionSweepInterval) {
|
private Disposable startSessionSweeper(Duration sessionSweepInterval) {
|
||||||
return Flux.interval(sessionSweepInterval, sessionSweepInterval, Schedulers.boundedElastic()).doOnNext(tick -> {
|
return Flux.interval(sessionSweepInterval, sessionSweepInterval, Schedulers.boundedElastic())
|
||||||
// Each sweep runs in its own subscription, so that a sweep failing does
|
.concatMap(
|
||||||
// not terminate the interval and disable sweeping altogether
|
tick -> sweepSessions().doOnError(e -> logger.error("Session sweep failed", e)).onErrorComplete())
|
||||||
Mono.fromRunnable(this::sweepSessions)
|
.onErrorComplete(error -> {
|
||||||
.doOnError(e -> logger.error("Session sweep failed", e))
|
logger.error("Session sweeper error", error);
|
||||||
.onErrorComplete()
|
return true;
|
||||||
.subscribe();
|
})
|
||||||
}).onErrorComplete(error -> {
|
.subscribe();
|
||||||
logger.error("Session sweeper error", error);
|
|
||||||
return true;
|
|
||||||
}).subscribe();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -235,25 +232,23 @@ public class HttpServletStreamableServerTransportProvider extends HttpServlet
|
||||||
* if it received a request during the interval which just elapsed. Anything else is a
|
* if it received a request during the interval which just elapsed. Anything else is a
|
||||||
* session whose client went away without deleting it: the protocol lets a client
|
* session whose client went away without deleting it: the protocol lets a client
|
||||||
* reconnect to a session, so nothing else ever reclaims it.
|
* reconnect to a session, so nothing else ever reclaims it.
|
||||||
|
* @return a Mono completing once every evicted session has been closed
|
||||||
*/
|
*/
|
||||||
private void sweepSessions() {
|
private Mono<Void> sweepSessions() {
|
||||||
if (this.isClosing) {
|
if (this.isClosing) {
|
||||||
return;
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
Set<String> active = this.activeSessions.getAndSet(ConcurrentHashMap.newKeySet());
|
Set<String> active = this.activeSessions.getAndSet(ConcurrentHashMap.newKeySet());
|
||||||
this.sessions.values().removeIf(session -> {
|
return Flux.fromIterable(this.sessions.values())
|
||||||
if (session.hasOpenStream() || active.contains(session.getId())) {
|
.filter(session -> !session.hasOpenStream() && !active.contains(session.getId()))
|
||||||
return false;
|
.filter(session -> this.sessions.remove(session.getId(), session))
|
||||||
}
|
.flatMap(session -> {
|
||||||
logger.debug("Evicting idle session {}", session.getId());
|
logger.debug("Evicting idle session {}", session.getId());
|
||||||
try {
|
return session.closeGracefully()
|
||||||
session.closeGracefully().block();
|
.doOnError(e -> logger.warn("Failed to close idle session {}: {}", session.getId(), e.getMessage()))
|
||||||
}
|
.onErrorComplete();
|
||||||
catch (Exception e) {
|
})
|
||||||
logger.warn("Failed to close idle session {}: {}", session.getId(), e.getMessage());
|
.then();
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue