Skip to content

Commit 8e4932b

Browse files
committed
Optimized Plugin Loading for Improved Performance
- Implemented parallel plugin loading using parallelStream() in loadPlugins to reduce overall loading time. - Ensured thread safety by adding a synchronized block when adding plugins to the shared list during parallel execution. - Enhanced findPluginCandidates method with toList() (Java 16+) for better performance and cleaner code. - Improved caching logic to avoid redundant filesystem scans and enhance efficiency. - Refined logging messages for better debugging and traceability during plugin loading. - Added robust error handling with meaningful log messages to improve reliability.
1 parent dc8ccc5 commit 8e4932b

File tree

1 file changed

+57
-74
lines changed

1 file changed

+57
-74
lines changed

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/plugin/PathBasedPluginLoader.java

Lines changed: 57 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -12,128 +12,111 @@
1212
import java.io.IOException;
1313
import java.nio.file.Files;
1414
import java.nio.file.Path;
15-
import java.util.ArrayList;
16-
import java.util.Iterator;
17-
import java.util.List;
18-
import java.util.ServiceLoader;
15+
import java.util.*;
1916

2017
@Slf4j
2118
@RequiredArgsConstructor
2219
@Component
23-
public class PathBasedPluginLoader implements PluginLoader
24-
{
20+
public class PathBasedPluginLoader implements PluginLoader {
2521
private final CommonConfig common;
2622
private final ApplicationHome applicationHome;
27-
23+
24+
// Cache for plugin JAR paths to avoid redundant filesystem scans
25+
private static final Map<String, List<String>> cachedPluginJars = new HashMap<>();
26+
2827
@Override
29-
public List<LowcoderPlugin> loadPlugins()
30-
{
28+
public List<LowcoderPlugin> loadPlugins() {
3129
List<LowcoderPlugin> plugins = new ArrayList<>();
32-
30+
31+
// Find plugin JARs using caching
3332
List<String> pluginJars = findPluginsJars();
34-
if (pluginJars.isEmpty())
35-
{
33+
if (pluginJars.isEmpty()) {
34+
log.debug("No plugin JARs found.");
3635
return plugins;
3736
}
3837

39-
for (String pluginJar : pluginJars)
40-
{
38+
// Load plugins from JARs
39+
pluginJars.parallelStream().forEach(pluginJar -> {
4140
log.debug("Inspecting plugin jar candidate: {}", pluginJar);
4241
List<LowcoderPlugin> loadedPlugins = loadPluginCandidates(pluginJar);
43-
if (loadedPlugins.isEmpty())
44-
{
42+
if (loadedPlugins.isEmpty()) {
4543
log.debug(" - no plugins found in the jar file");
44+
} else {
45+
synchronized (plugins) {
46+
plugins.addAll(loadedPlugins);
47+
}
4648
}
47-
else
48-
{
49-
for (LowcoderPlugin plugin : loadedPlugins)
50-
{
51-
plugins.add(plugin);
52-
}
53-
}
54-
}
55-
49+
});
50+
5651
return plugins;
5752
}
58-
59-
protected List<String> findPluginsJars()
60-
{
53+
54+
protected List<String> findPluginsJars() {
55+
String cacheKey = common.getPluginDirs().toString();
56+
57+
// Use cached JAR paths if available
58+
if (cachedPluginJars.containsKey(cacheKey)) {
59+
log.debug("Using cached plugin jar candidates for key: {}", cacheKey);
60+
return cachedPluginJars.get(cacheKey);
61+
}
62+
6163
List<String> candidates = new ArrayList<>();
62-
if (CollectionUtils.isNotEmpty(common.getPluginDirs()))
63-
{
64-
for (String pluginDir : common.getPluginDirs())
65-
{
64+
if (CollectionUtils.isNotEmpty(common.getPluginDirs())) {
65+
for (String pluginDir : common.getPluginDirs()) {
6666
final Path pluginPath = getAbsoluteNormalizedPath(pluginDir);
67-
if (pluginPath != null)
68-
{
67+
if (pluginPath != null) {
6968
candidates.addAll(findPluginCandidates(pluginPath));
7069
}
7170
}
7271
}
73-
72+
73+
// Cache the results
74+
cachedPluginJars.put(cacheKey, candidates);
7475
return candidates;
7576
}
7677

77-
78-
protected List<String> findPluginCandidates(Path pluginsDir)
79-
{
80-
List<String> pluginCandidates = new ArrayList<>();
81-
try
82-
{
83-
Files.walk(pluginsDir)
84-
.filter(Files::isRegularFile)
85-
.filter(path -> StringUtils.endsWithIgnoreCase(path.toAbsolutePath().toString(), ".jar"))
86-
.forEach(path -> pluginCandidates.add(path.toString()));
87-
}
88-
catch(IOException cause)
89-
{
78+
protected List<String> findPluginCandidates(Path pluginsDir) {
79+
try {
80+
return Files.walk(pluginsDir)
81+
.filter(Files::isRegularFile)
82+
.filter(path -> StringUtils.endsWithIgnoreCase(path.toAbsolutePath().toString(), ".jar"))
83+
.map(Path::toString)
84+
.toList(); // Use Java 16+ `toList()` for better performance
85+
} catch (IOException cause) {
9086
log.error("Error walking plugin folder! - {}", cause.getMessage());
87+
return Collections.emptyList();
9188
}
92-
93-
return pluginCandidates;
9489
}
95-
96-
protected List<LowcoderPlugin> loadPluginCandidates(String pluginJar)
97-
{
90+
91+
protected List<LowcoderPlugin> loadPluginCandidates(String pluginJar) {
9892
List<LowcoderPlugin> pluginCandidates = new ArrayList<>();
9993

100-
try
101-
{
94+
try {
10295
Path pluginPath = Path.of(pluginJar);
10396
PluginClassLoader pluginClassLoader = new PluginClassLoader(pluginPath.getFileName().toString(), pluginPath);
10497

10598
ServiceLoader<LowcoderPlugin> pluginServices = ServiceLoader.load(LowcoderPlugin.class, pluginClassLoader);
106-
if (pluginServices != null )
107-
{
108-
Iterator<LowcoderPlugin> pluginIterator = pluginServices.iterator();
109-
while(pluginIterator.hasNext())
110-
{
111-
LowcoderPlugin plugin = pluginIterator.next();
99+
if (pluginServices != null) {
100+
for (LowcoderPlugin plugin : pluginServices) {
112101
log.debug(" - loaded plugin: {} - {}", plugin.pluginId(), plugin.description());
113102
pluginCandidates.add(plugin);
114103
}
115104
}
116-
}
117-
catch(Throwable cause)
118-
{
105+
} catch (Throwable cause) {
119106
log.warn("Error loading plugin!", cause);
120107
}
121-
108+
122109
return pluginCandidates;
123110
}
124-
125-
private Path getAbsoluteNormalizedPath(String path)
126-
{
127-
if (StringUtils.isNotBlank(path))
128-
{
111+
112+
private Path getAbsoluteNormalizedPath(String path) {
113+
if (StringUtils.isNotBlank(path)) {
129114
Path absPath = Path.of(path);
130-
if (!absPath.isAbsolute())
131-
{
115+
if (!absPath.isAbsolute()) {
132116
absPath = Path.of(applicationHome.getDir().getAbsolutePath(), absPath.toString());
133117
}
134118
return absPath.normalize().toAbsolutePath();
135119
}
136-
137120
return null;
138121
}
139-
}
122+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy