fix: failed to load plugin when add fixedPluginPath dynamically in development mode (#2941)

#### What type of PR is this?
/kind bug
/area core

#### What this PR does / why we need it:
修复插件开发模式下后续增加的 fixedPluginPath 项无法被加载的问题
- 目前启动时会加载 pluginRepository 的所有 path,fixedPluginPath 被 DefaultDevelopmentPluginRepository 管理,所以在遍历 fixedPluginPath 加载时可能已经被加载过,需要判断是否被加载过,但即使被加载过也不能跳过而要继续执行创建/更新 plugin.yaml 资源的逻辑
- 创建/更新 plugin.yaml 时需要使用重试机制防止因为乐观锁冲突导致 Halo 无法启动

see #2939 for more detail
#### Which issue(s) this PR fixes:

Fixes #2939

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
修复插件开发模式下后续增加的 fixedPluginPath 项无法被加载的问题
```
pull/2923/head
guqing 2022-12-14 15:49:23 +08:00 committed by GitHub
parent df0e6cff49
commit 07f5b0dbcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 24 additions and 17 deletions

View File

@ -1,14 +1,18 @@
package run.halo.app.plugin;
import java.nio.file.Path;
import java.time.Duration;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginWrapper;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.Plugin;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ReactiveExtensionClient;
/**
* @author guqing
@ -22,10 +26,10 @@ public class PluginDevelopmentInitializer implements ApplicationListener<Applica
private final PluginProperties pluginProperties;
private final ExtensionClient extensionClient;
private final ReactiveExtensionClient extensionClient;
public PluginDevelopmentInitializer(HaloPluginManager haloPluginManager,
PluginProperties pluginProperties, ExtensionClient extensionClient) {
PluginProperties pluginProperties, ReactiveExtensionClient extensionClient) {
this.haloPluginManager = haloPluginManager;
this.pluginProperties = pluginProperties;
this.extensionClient = extensionClient;
@ -41,19 +45,18 @@ public class PluginDevelopmentInitializer implements ApplicationListener<Applica
private void createFixedPluginIfNecessary(HaloPluginManager pluginManager) {
for (Path path : pluginProperties.getFixedPluginPath()) {
// already loaded
if (idForPath(path) != null) {
continue;
}
// Already loaded do not load again
String pluginId = idForPath(path);
// for issue #2901
String pluginId;
try {
pluginId = pluginManager.loadPlugin(path);
} catch (Exception e) {
log.warn(e.getMessage(), e);
continue;
if (pluginId == null) {
try {
pluginId = pluginManager.loadPlugin(path);
} catch (Exception e) {
log.warn(e.getMessage(), e);
continue;
}
}
PluginWrapper pluginWrapper = pluginManager.getPlugin(pluginId);
@ -62,10 +65,14 @@ public class PluginDevelopmentInitializer implements ApplicationListener<Applica
}
Plugin plugin = new YamlPluginFinder().find(pluginWrapper.getPluginPath());
extensionClient.fetch(Plugin.class, plugin.getMetadata().getName())
.ifPresentOrElse(persistent -> {
.flatMap(persistent -> {
plugin.getMetadata().setVersion(persistent.getMetadata().getVersion());
extensionClient.update(plugin);
}, () -> extensionClient.create(plugin));
return extensionClient.update(plugin);
})
.switchIfEmpty(Mono.defer(() -> extensionClient.create(plugin)))
.retryWhen(Retry.backoff(10, Duration.ofMillis(100))
.filter(t -> t instanceof OptimisticLockingFailureException))
.block();
}
}