Polishing in WebAsyncManager
See gh-34192
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -288,55 +288,8 @@ public class DeferredResult<T> {
|
||||
}
|
||||
|
||||
|
||||
final DeferredResultProcessingInterceptor getInterceptor() {
|
||||
return new DeferredResultProcessingInterceptor() {
|
||||
@Override
|
||||
public <S> boolean handleTimeout(NativeWebRequest request, DeferredResult<S> deferredResult) {
|
||||
boolean continueProcessing = true;
|
||||
try {
|
||||
if (timeoutCallback != null) {
|
||||
timeoutCallback.run();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Object value = timeoutResult.get();
|
||||
if (value != RESULT_NONE) {
|
||||
continueProcessing = false;
|
||||
try {
|
||||
setResultInternal(value);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Failed to handle timeout result", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return continueProcessing;
|
||||
}
|
||||
@Override
|
||||
public <S> boolean handleError(NativeWebRequest request, DeferredResult<S> deferredResult, Throwable t) {
|
||||
try {
|
||||
if (errorCallback != null) {
|
||||
errorCallback.accept(t);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
setResultInternal(t);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Failed to handle error result", ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public <S> void afterCompletion(NativeWebRequest request, DeferredResult<S> deferredResult) {
|
||||
expired = true;
|
||||
if (completionCallback != null) {
|
||||
completionCallback.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
final DeferredResultProcessingInterceptor getLifecycleInterceptor() {
|
||||
return new LifecycleInterceptor();
|
||||
}
|
||||
|
||||
|
||||
@@ -349,4 +302,61 @@ public class DeferredResult<T> {
|
||||
void handleResult(@Nullable Object result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instance interceptor to receive Servlet container notifications.
|
||||
*/
|
||||
private class LifecycleInterceptor implements DeferredResultProcessingInterceptor {
|
||||
|
||||
@Override
|
||||
public <S> boolean handleTimeout(NativeWebRequest request, DeferredResult<S> result) {
|
||||
boolean continueProcessing = true;
|
||||
try {
|
||||
if (timeoutCallback != null) {
|
||||
timeoutCallback.run();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Object value = timeoutResult.get();
|
||||
if (value != RESULT_NONE) {
|
||||
continueProcessing = false;
|
||||
try {
|
||||
setResultInternal(value);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Failed to handle timeout result", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return continueProcessing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> boolean handleError(NativeWebRequest request, DeferredResult<S> result, Throwable t) {
|
||||
try {
|
||||
if (errorCallback != null) {
|
||||
errorCallback.accept(t);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
setResultInternal(t);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Failed to handle error result", ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> void afterCompletion(NativeWebRequest request, DeferredResult<S> result) {
|
||||
expired = true;
|
||||
if (completionCallback != null) {
|
||||
completionCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -383,36 +383,6 @@ public final class WebAsyncManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void setConcurrentResultAndDispatch(@Nullable Object result) {
|
||||
Assert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
|
||||
synchronized (WebAsyncManager.this) {
|
||||
if (!this.state.compareAndSet(State.ASYNC_PROCESSING, State.RESULT_SET)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Async result already set: [" + this.state.get() +
|
||||
"], ignored result for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.concurrentResult = result;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Async result set for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
|
||||
if (this.asyncWebRequest.isAsyncComplete()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Async request already completed for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Performing async dispatch for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
this.asyncWebRequest.dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start concurrent request processing and initialize the given
|
||||
* {@link DeferredResult} with a {@link DeferredResultHandler} that saves
|
||||
@@ -445,7 +415,7 @@ public final class WebAsyncManager {
|
||||
}
|
||||
|
||||
List<DeferredResultProcessingInterceptor> interceptors = new ArrayList<>();
|
||||
interceptors.add(deferredResult.getInterceptor());
|
||||
interceptors.add(deferredResult.getLifecycleInterceptor());
|
||||
interceptors.addAll(this.deferredResultInterceptors.values());
|
||||
interceptors.add(timeoutDeferredResultInterceptor);
|
||||
|
||||
@@ -510,6 +480,36 @@ public final class WebAsyncManager {
|
||||
this.asyncWebRequest.startAsync();
|
||||
}
|
||||
|
||||
private void setConcurrentResultAndDispatch(@Nullable Object result) {
|
||||
Assert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
|
||||
synchronized (WebAsyncManager.this) {
|
||||
if (!this.state.compareAndSet(State.ASYNC_PROCESSING, State.RESULT_SET)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Async result already set: [" + this.state.get() + "], " +
|
||||
"ignored result for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.concurrentResult = result;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Async result set for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
|
||||
if (this.asyncWebRequest.isAsyncComplete()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Async request already completed for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Performing async dispatch for " + formatUri(this.asyncWebRequest));
|
||||
}
|
||||
this.asyncWebRequest.dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatUri(AsyncWebRequest asyncWebRequest) {
|
||||
HttpServletRequest request = asyncWebRequest.getNativeRequest(HttpServletRequest.class);
|
||||
return (request != null ? "\"" + request.getRequestURI() + "\"" : "servlet container");
|
||||
@@ -519,13 +519,13 @@ public final class WebAsyncManager {
|
||||
/**
|
||||
* Represents a state for {@link WebAsyncManager} to be in.
|
||||
* <p><pre>
|
||||
* NOT_STARTED <------+
|
||||
* | |
|
||||
* v |
|
||||
* ASYNC_PROCESSING |
|
||||
* | |
|
||||
* v |
|
||||
* RESULT_SET -------+
|
||||
* +------> NOT_STARTED <------+
|
||||
* | | |
|
||||
* | v |
|
||||
* | ASYNC_PROCESSING |
|
||||
* | | |
|
||||
* | v |
|
||||
* <-------+ RESULT_SET -------+
|
||||
* </pre>
|
||||
* @since 5.3.33
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user