Skip to content

Commit 0455a6c

Browse files
authored
Refactor plugin start task management to ensure cancellation of existing tasks (#8170)
1 parent ffdc6d3 commit 0455a6c

1 file changed

Lines changed: 35 additions & 19 deletions

File tree

application/src/main/java/run/halo/app/core/reconciler/PluginReconciler.java

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ private Result enablePlugin(Plugin plugin) {
337337
.lastTransitionTime(clock.instant())
338338
.build());
339339
status.setPhase(Plugin.Phase.FAILED);
340+
removeStartTaskIfPresent(pluginName);
340341
return Result.doNotRetry();
341342
}
342343
var pluginState = current.getPluginState();
@@ -351,8 +352,9 @@ private Result enablePlugin(Plugin plugin) {
351352
.lastTransitionTime(clock.instant())
352353
.build());
353354
status.setPhase(Plugin.Phase.STARTED);
355+
removeStartTaskIfPresent(pluginName);
354356
requestToReloadPluginsOptionallyDependentOn(pluginName);
355-
return null;
357+
return Result.doNotRetry();
356358
}
357359
if (pluginState.isFailed()) {
358360
var t = current.getFailedException();
@@ -367,22 +369,30 @@ private Result enablePlugin(Plugin plugin) {
367369
.lastTransitionTime(clock.instant())
368370
.build());
369371
status.setPhase(Plugin.Phase.FAILED);
372+
removeStartTaskIfPresent(pluginName);
370373
return Result.doNotRetry();
371374
}
372375
if (!Plugin.Phase.STARTING.equals(status.getPhase())) {
373-
pluginStartTasks.computeIfAbsent(pluginName, name -> scheduler.schedule(() -> {
374-
log.info("Starting plugin {} in background thread.", name);
375-
try {
376-
var state = pluginManager.startPlugin(name);
377-
log.info("Plugin {} started with state {}.", name, state);
378-
} catch (Throwable t) {
379-
var pluginWrapper = pluginManager.getPlugin(name);
380-
if (pluginWrapper != null) {
381-
pluginWrapper.setPluginState(PluginState.FAILED);
382-
pluginWrapper.setFailedException(t);
383-
}
376+
pluginStartTasks.compute(pluginName, (name, old) -> {
377+
if (old != null && !old.isDisposed()) {
378+
log.info("Cancelling old starting task for plugin {}.", name);
379+
old.dispose();
380+
log.info("Cancelled old starting task for plugin {}.", name);
384381
}
385-
}));
382+
return scheduler.schedule(() -> {
383+
log.info("Starting plugin {} in background thread.", name);
384+
try {
385+
var state = pluginManager.startPlugin(name);
386+
log.info("Plugin {} started with state {}.", name, state);
387+
} catch (Throwable t) {
388+
var pluginWrapper = pluginManager.getPlugin(name);
389+
if (pluginWrapper != null) {
390+
pluginWrapper.setPluginState(PluginState.FAILED);
391+
pluginWrapper.setFailedException(t);
392+
}
393+
}
394+
});
395+
});
386396
status.setPhase(Plugin.Phase.STARTING);
387397
conditions.addAndEvictFIFO(Condition.builder()
388398
.type(ConditionType.PROGRESSING)
@@ -441,12 +451,7 @@ private Result disablePlugin(Plugin plugin) {
441451
}
442452
try {
443453
// First, stop starting task if exists
444-
pluginStartTasks.computeIfPresent(pluginName, (name, disposable) -> {
445-
log.info("Cancelling starting task for plugin {}.", name);
446-
disposable.dispose();
447-
log.info("Cancelled starting task for plugin {}.", name);
448-
return null;
449-
});
454+
removeStartTaskIfPresent(pluginName);
450455
pluginManager.disablePlugin(pluginName);
451456
} catch (Throwable e) {
452457
conditions.addAndEvictFIFO(Condition.builder()
@@ -805,6 +810,17 @@ public Controller setupWith(ControllerBuilder builder) {
805810
.build();
806811
}
807812

813+
private void removeStartTaskIfPresent(String pluginName) {
814+
pluginStartTasks.computeIfPresent(pluginName, (name, disposable) -> {
815+
if (!disposable.isDisposed()) {
816+
log.info("Cancelling starting task for plugin {}.", name);
817+
disposable.dispose();
818+
log.info("Cancelled starting task for plugin {}.", name);
819+
}
820+
return null;
821+
});
822+
}
823+
808824
private Result createOrUpdateReverseProxy(Plugin plugin) {
809825
String pluginName = plugin.getMetadata().getName();
810826
String reverseProxyName = buildReverseProxyName(pluginName);

0 commit comments

Comments
 (0)