mirror of https://github.com/halo-dev/halo
Fix the issue with repeatedly building plugin RouterFunction for CustomEndpoints (#4890)
* fix: OOM occured when using ab to test custom endpoints provided by plugin * refactor: custom endpoints to rotuer function register for plugin * refactor: bean post processor register * Register AggregatedRouterFunction bean instead of adding bean factory post processor * Remove debug lines --------- Co-authored-by: John Niang <johnniang@foxmail.com>pull/4910/head
parent
4ee4a8fd36
commit
57a1f2ec18
|
@ -0,0 +1,38 @@
|
|||
package run.halo.app.plugin;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.web.reactive.function.server.HandlerFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
|
||||
|
||||
/**
|
||||
* Aggregated router function built from all custom endpoints.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public class AggregatedRouterFunction implements RouterFunction<ServerResponse> {
|
||||
|
||||
private final RouterFunction<ServerResponse> aggregated;
|
||||
|
||||
public AggregatedRouterFunction(ObjectProvider<CustomEndpoint> customEndpoints) {
|
||||
var builder = new CustomEndpointsBuilder();
|
||||
customEndpoints.orderedStream()
|
||||
.forEach(builder::add);
|
||||
this.aggregated = builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<HandlerFunction<ServerResponse>> route(ServerRequest request) {
|
||||
return aggregated.route(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RouterFunctions.Visitor visitor) {
|
||||
this.aggregated.accept(visitor);
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import run.halo.app.infra.properties.HaloProperties;
|
|||
*/
|
||||
@Slf4j
|
||||
public class PluginApplicationInitializer {
|
||||
|
||||
protected final HaloPluginManager haloPluginManager;
|
||||
|
||||
private final ExtensionContextRegistry contextRegistry = ExtensionContextRegistry.getInstance();
|
||||
|
@ -89,6 +90,8 @@ public class PluginApplicationInitializer {
|
|||
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
|
||||
stopWatch.stop();
|
||||
|
||||
pluginApplicationContext.registerBean(AggregatedRouterFunction.class);
|
||||
|
||||
beanFactory.registerSingleton("pluginContext", createPluginContext(plugin));
|
||||
// TODO deprecated
|
||||
beanFactory.registerSingleton("pluginWrapper", haloPluginManager.getPlugin(pluginId));
|
||||
|
|
|
@ -2,7 +2,7 @@ package run.halo.app.plugin;
|
|||
|
||||
import static run.halo.app.plugin.ExtensionContextRegistry.getInstance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.List;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
@ -14,8 +14,6 @@ import org.springframework.web.reactive.function.server.ServerRequest;
|
|||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
|
||||
import run.halo.app.plugin.resources.ReverseProxyRouterFunctionRegistry;
|
||||
|
||||
/**
|
||||
|
@ -48,7 +46,7 @@ public class PluginCompositeRouterFunction implements RouterFunction<ServerRespo
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<RouterFunction<ServerResponse>> routerFunctions() {
|
||||
private Iterable<RouterFunction<ServerResponse>> routerFunctions() {
|
||||
getInstance().acquireReadLock();
|
||||
try {
|
||||
List<PluginApplicationContext> contexts = getInstance().getPluginApplicationContexts()
|
||||
|
@ -64,18 +62,7 @@ public class PluginCompositeRouterFunction implements RouterFunction<ServerRespo
|
|||
.toList();
|
||||
var reverseProxies = reverseProxyRouterFunctionFactory.getRouterFunctions();
|
||||
|
||||
var endpointBuilder = new CustomEndpointsBuilder();
|
||||
contexts.forEach(context -> context.getBeanProvider(CustomEndpoint.class)
|
||||
.orderedStream()
|
||||
.forEach(endpointBuilder::add));
|
||||
var customEndpoint = endpointBuilder.build();
|
||||
|
||||
List<RouterFunction<ServerResponse>> routerFunctions =
|
||||
new ArrayList<>(rawRouterFunctions.size() + reverseProxies.size() + 1);
|
||||
routerFunctions.addAll(rawRouterFunctions);
|
||||
routerFunctions.addAll(reverseProxies);
|
||||
routerFunctions.add(customEndpoint);
|
||||
return routerFunctions;
|
||||
return Iterables.concat(rawRouterFunctions, reverseProxies);
|
||||
} finally {
|
||||
getInstance().releaseReadLock();
|
||||
}
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
package run.halo.app.plugin.event;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.pf4j.PluginWrapper;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* This event will be published to <b>application context</b> once plugin is started.
|
||||
*
|
||||
* @author guqing
|
||||
*/
|
||||
@Getter
|
||||
public class HaloPluginStartedEvent extends ApplicationEvent {
|
||||
|
||||
private final PluginWrapper plugin;
|
||||
|
||||
|
||||
public HaloPluginStartedEvent(Object source, PluginWrapper plugin) {
|
||||
super(source);
|
||||
Assert.notNull(plugin, "Plugin must not be null.");
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public PluginWrapper getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.springframework.web.reactive.function.server.support.RouterFunctionMa
|
|||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
||||
import run.halo.app.plugin.resources.ReverseProxyRouterFunctionRegistry;
|
||||
|
||||
/**
|
||||
|
@ -43,9 +42,6 @@ class PluginCompositeRouterFunctionTest {
|
|||
@Mock
|
||||
ObjectProvider<RouterFunction> rawRouterFunctionsProvider;
|
||||
|
||||
@Mock
|
||||
ObjectProvider<CustomEndpoint> customEndpointsProvider;
|
||||
|
||||
@InjectMocks
|
||||
PluginCompositeRouterFunction compositeRouterFunction;
|
||||
|
||||
|
@ -59,11 +55,9 @@ class PluginCompositeRouterFunctionTest {
|
|||
ExtensionContextRegistry.getInstance().register("fake-plugin", fakeContext);
|
||||
|
||||
when(rawRouterFunctionsProvider.orderedStream()).thenReturn(Stream.empty());
|
||||
when(customEndpointsProvider.orderedStream()).thenReturn(Stream.empty());
|
||||
|
||||
when(fakeContext.getBeanProvider(RouterFunction.class))
|
||||
.thenReturn(rawRouterFunctionsProvider);
|
||||
when(fakeContext.getBeanProvider(CustomEndpoint.class)).thenReturn(customEndpointsProvider);
|
||||
|
||||
compositeRouterFunction =
|
||||
new PluginCompositeRouterFunction(reverseProxyRouterFunctionRegistry);
|
||||
|
@ -93,11 +87,10 @@ class PluginCompositeRouterFunctionTest {
|
|||
.verify();
|
||||
|
||||
verify(rawRouterFunctionsProvider).orderedStream();
|
||||
verify(customEndpointsProvider).orderedStream();
|
||||
}
|
||||
|
||||
private ServerWebExchange createExchange(String urlTemplate) {
|
||||
return MockServerWebExchange.from(MockServerHttpRequest.get(urlTemplate));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue