Skip to content

Commit

Permalink
fix: OOM occured when using ab to test custom endpoints provided by p…
Browse files Browse the repository at this point in the history
…lugin
  • Loading branch information
guqing committed Nov 22, 2023
1 parent aa9f84e commit ddd60e4
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 29 deletions.
Expand Up @@ -2,7 +2,7 @@

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;
Expand All @@ -14,8 +14,6 @@
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;

/**
Expand Down Expand Up @@ -48,7 +46,7 @@ public void accept(@NonNull RouterFunctions.Visitor visitor) {
}

@SuppressWarnings("unchecked")
private List<RouterFunction<ServerResponse>> routerFunctions() {
private Iterable<RouterFunction<ServerResponse>> routerFunctions() {
getInstance().acquireReadLock();
try {
List<PluginApplicationContext> contexts = getInstance().getPluginApplicationContexts()
Expand All @@ -64,18 +62,7 @@ private List<RouterFunction<ServerResponse>> routerFunctions() {
.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();
}
Expand Down
@@ -0,0 +1,43 @@
package run.halo.app.plugin;

import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.RouterFunction;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
import run.halo.app.plugin.event.HaloPluginStartedEvent;

/**
* <p>An Initialization class for plugin's {@link RouterFunction}.</p>
*
* @author guqing
* @since 2.11.0
*/
@Component
@RequiredArgsConstructor
public class PluginCustomEndpointInitialization {

private final HaloPluginManager haloPluginManager;

/**
* Get all {@link CustomEndpoint} beans from plugin's {@link PluginApplicationContext} and
* create a {@link RouterFunction} for them to register to the bean factory on plugin startup.
*/
@Async
@EventListener(HaloPluginStartedEvent.class)
public void onPluginStartUp(HaloPluginStartedEvent event) {
var pluginName = event.getPlugin().getPluginId();
var applicationContext = haloPluginManager.getPluginApplicationContext(pluginName);

var endpoints = applicationContext.getBeansOfType(CustomEndpoint.class).values();
if (endpoints.isEmpty()) {
return;
}
var endpointBuilder = new CustomEndpointsBuilder();
endpoints.forEach(endpointBuilder::add);
applicationContext.registerBean("pluginCustomEndpointRouter",
RouterFunction.class, endpointBuilder::build);
}
}
@@ -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;
}
}
Expand Up @@ -24,7 +24,6 @@
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;

/**
Expand All @@ -43,9 +42,6 @@ class PluginCompositeRouterFunctionTest {
@Mock
ObjectProvider<RouterFunction> rawRouterFunctionsProvider;

@Mock
ObjectProvider<CustomEndpoint> customEndpointsProvider;

@InjectMocks
PluginCompositeRouterFunction compositeRouterFunction;

Expand All @@ -59,11 +55,9 @@ void setUp() {
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);
Expand Down Expand Up @@ -93,11 +87,10 @@ void route() {
.verify();

verify(rawRouterFunctionsProvider).orderedStream();
verify(customEndpointsProvider).orderedStream();
}

private ServerWebExchange createExchange(String urlTemplate) {
return MockServerWebExchange.from(MockServerHttpRequest.get(urlTemplate));
}

}
}

0 comments on commit ddd60e4

Please sign in to comment.