mirror of https://github.com/halo-dev/halo
Enable defining Reconciler in plugin (#3789)
#### What type of PR is this? /kind feature /area core /area plugin #### What this PR does / why we need it: This PR adds reconciliation mechanism for plugin. After that, we could define a `Reconciler<Request>` like the following when developing plugin: ```java @Slf4j @Component public class ApplicationReconciler implements Reconciler<Reconciler.Request> { @Override public Result reconcile(Request request) { log.info("Application {} changed.", request); return Result.doNotRetry(); } @Override public Controller setupWith(ControllerBuilder builder) { return builder .extension(new Application()) .workerCount(1) .build(); } } ``` You can reconcile any extensions as needed. Meanwhile, all plugins will be stopped when Halo is shutting down. #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/3783 #### Does this PR introduce a user-facing change? ```release-note 支持在插件中定义 Reconciler ```pull/3744/head
parent
7afb3b8687
commit
11a5807682
|
@ -21,6 +21,7 @@ import org.pf4j.PluginState;
|
|||
import org.pf4j.PluginStateEvent;
|
||||
import org.pf4j.PluginWrapper;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
@ -41,7 +42,7 @@ import run.halo.app.plugin.event.HaloPluginStoppedEvent;
|
|||
*/
|
||||
@Slf4j
|
||||
public class HaloPluginManager extends DefaultPluginManager
|
||||
implements ApplicationContextAware, InitializingBean {
|
||||
implements ApplicationContextAware, InitializingBean, DisposableBean {
|
||||
|
||||
private final Map<String, PluginStartingError> startingErrors = new HashMap<>();
|
||||
|
||||
|
@ -403,5 +404,10 @@ public class HaloPluginManager extends DefaultPluginManager
|
|||
springComponentsFinder.removeComponentsStorage(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
stopPlugins();
|
||||
}
|
||||
// end-region
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package run.halo.app.plugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.extension.ExtensionClient;
|
||||
import run.halo.app.extension.controller.ControllerManager;
|
||||
import run.halo.app.extension.controller.DefaultControllerManager;
|
||||
import run.halo.app.extension.controller.Reconciler;
|
||||
import run.halo.app.extension.controller.Reconciler.Request;
|
||||
import run.halo.app.plugin.event.HaloPluginBeforeStopEvent;
|
||||
import run.halo.app.plugin.event.HaloPluginStartedEvent;
|
||||
|
||||
@Component
|
||||
public class PluginControllerManager {
|
||||
|
||||
private final Map<String, ControllerManager> controllerManagerMap;
|
||||
|
||||
private final ExtensionClient client;
|
||||
|
||||
public PluginControllerManager(ExtensionClient client) {
|
||||
this.client = client;
|
||||
controllerManagerMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void onPluginStarted(HaloPluginStartedEvent event) {
|
||||
var plugin = event.getPlugin();
|
||||
|
||||
var controllerManager = controllerManagerMap.computeIfAbsent(plugin.getPluginId(),
|
||||
id -> new DefaultControllerManager(client));
|
||||
|
||||
getReconcilers(plugin.getPluginId())
|
||||
.forEach(controllerManager::start);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void onPluginBeforeStop(HaloPluginBeforeStopEvent event) {
|
||||
// remove controller manager
|
||||
var plugin = event.getPlugin();
|
||||
var controllerManager = controllerManagerMap.remove(plugin.getPluginId());
|
||||
if (controllerManager != null) {
|
||||
// stop all reconcilers
|
||||
getReconcilers(plugin.getPluginId())
|
||||
.forEach(controllerManager::stop);
|
||||
}
|
||||
}
|
||||
|
||||
private Stream<Reconciler<Request>> getReconcilers(String pluginId) {
|
||||
var context = ExtensionContextRegistry.getInstance().getByPluginId(pluginId);
|
||||
return context.<Reconciler<Request>>getBeanProvider(
|
||||
ResolvableType.forClassWithGenerics(Reconciler.class, Request.class))
|
||||
.orderedStream();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue