refactor: clear the template cache after uninstalling the theme (#7174)

#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x

#### What this PR does / why we need it:
卸载主题之后清理模板缓存

此问题是 https://github.com/halo-dev/halo/pull/2970 的遗留问题

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/7199/head
guqing 2025-01-03 17:34:10 +08:00 committed by GitHub
parent 24f8d7b571
commit be6f044a29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 11 deletions

View File

@ -10,6 +10,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.retry.support.RetryTemplate; import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -31,6 +32,7 @@ import run.halo.app.infra.exception.ThemeUninstallException;
import run.halo.app.infra.utils.JsonUtils; import run.halo.app.infra.utils.JsonUtils;
import run.halo.app.infra.utils.SettingUtils; import run.halo.app.infra.utils.SettingUtils;
import run.halo.app.infra.utils.VersionUtils; import run.halo.app.infra.utils.VersionUtils;
import run.halo.app.theme.TemplateEngineManager;
/** /**
* Reconciler for theme. * Reconciler for theme.
@ -39,6 +41,7 @@ import run.halo.app.infra.utils.VersionUtils;
* @since 2.0.0 * @since 2.0.0
*/ */
@Component @Component
@RequiredArgsConstructor
public class ThemeReconciler implements Reconciler<Request> { public class ThemeReconciler implements Reconciler<Request> {
private static final String FINALIZER_NAME = "theme-protection"; private static final String FINALIZER_NAME = "theme-protection";
@ -46,6 +49,7 @@ public class ThemeReconciler implements Reconciler<Request> {
private final ThemeRootGetter themeRoot; private final ThemeRootGetter themeRoot;
private final SystemVersionSupplier systemVersionSupplier; private final SystemVersionSupplier systemVersionSupplier;
private final TemplateEngineManager templateEngineManager;
private final RetryTemplate retryTemplate = RetryTemplate.builder() private final RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(20) .maxAttempts(20)
@ -53,13 +57,6 @@ public class ThemeReconciler implements Reconciler<Request> {
.retryOn(IllegalStateException.class) .retryOn(IllegalStateException.class)
.build(); .build();
public ThemeReconciler(ExtensionClient client, ThemeRootGetter themeRoot,
SystemVersionSupplier systemVersionSupplier) {
this.client = client;
this.themeRoot = themeRoot;
this.systemVersionSupplier = systemVersionSupplier;
}
@Override @Override
public Result reconcile(Request request) { public Result reconcile(Request request) {
client.fetch(Theme.class, request.name()) client.fetch(Theme.class, request.name())
@ -173,6 +170,7 @@ public class ThemeReconciler implements Reconciler<Request> {
} }
private void reconcileThemeDeletion(Theme theme) { private void reconcileThemeDeletion(Theme theme) {
templateEngineManager.clearCache(theme.getMetadata().getName()).block();
deleteThemeFiles(theme); deleteThemeFiles(theme);
// delete theme setting form // delete theme setting form
String settingName = theme.getSpec().getSettingName(); String settingName = theme.getSpec().getSettingName();

View File

@ -32,10 +32,10 @@ import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.retry.RetryException; import org.springframework.retry.RetryException;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.AnnotationSetting; import run.halo.app.core.extension.AnnotationSetting;
import run.halo.app.core.extension.Setting; import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.Theme; import run.halo.app.core.extension.Theme;
import run.halo.app.core.reconciler.ThemeReconciler;
import run.halo.app.extension.ConfigMap; import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.Metadata; import run.halo.app.extension.Metadata;
@ -44,6 +44,7 @@ import run.halo.app.extension.controller.Reconciler;
import run.halo.app.infra.SystemVersionSupplier; import run.halo.app.infra.SystemVersionSupplier;
import run.halo.app.infra.ThemeRootGetter; import run.halo.app.infra.ThemeRootGetter;
import run.halo.app.infra.utils.JsonUtils; import run.halo.app.infra.utils.JsonUtils;
import run.halo.app.theme.TemplateEngineManager;
/** /**
* Tests for {@link ThemeReconciler}. * Tests for {@link ThemeReconciler}.
@ -66,6 +67,9 @@ class ThemeReconcilerTest {
@Mock @Mock
private File defaultTheme; private File defaultTheme;
@Mock
private TemplateEngineManager templateEngineManager;
@InjectMocks @InjectMocks
ThemeReconciler themeReconciler; ThemeReconciler themeReconciler;
@ -76,6 +80,7 @@ class ThemeReconcilerTest {
void setUp() throws IOException { void setUp() throws IOException {
defaultTheme = ResourceUtils.getFile("classpath:themes/default"); defaultTheme = ResourceUtils.getFile("classpath:themes/default");
lenient().when(systemVersionSupplier.get()).thenReturn(Version.parse("0.0.0")); lenient().when(systemVersionSupplier.get()).thenReturn(Version.parse("0.0.0"));
lenient().when(templateEngineManager.clearCache(any())).thenReturn(Mono.empty());
} }
@Test @Test
@ -128,7 +133,8 @@ class ThemeReconcilerTest {
when(themeRoot.get()).thenReturn(testWorkDir); when(themeRoot.get()).thenReturn(testWorkDir);
final ThemeReconciler themeReconciler = final ThemeReconciler themeReconciler =
new ThemeReconciler(extensionClient, themeRoot, systemVersionSupplier); new ThemeReconciler(extensionClient, themeRoot, systemVersionSupplier,
templateEngineManager);
final int[] retryFlags = {0, 0}; final int[] retryFlags = {0, 0};
when(extensionClient.fetch(eq(Setting.class), eq("theme-test-setting"))) when(extensionClient.fetch(eq(Setting.class), eq("theme-test-setting")))
@ -157,6 +163,7 @@ class ThemeReconcilerTest {
verify(extensionClient, times(2)).fetch(eq(Theme.class), eq(metadata.getName())); verify(extensionClient, times(2)).fetch(eq(Theme.class), eq(metadata.getName()));
verify(extensionClient, times(3)).fetch(eq(Setting.class), eq(settingName)); verify(extensionClient, times(3)).fetch(eq(Setting.class), eq(settingName));
verify(extensionClient, times(3)).list(eq(AnnotationSetting.class), any(), eq(null)); verify(extensionClient, times(3)).list(eq(AnnotationSetting.class), any(), eq(null));
verify(templateEngineManager).clearCache(eq(metadata.getName()));
} }
@Test @Test
@ -167,7 +174,8 @@ class ThemeReconcilerTest {
when(themeRoot.get()).thenReturn(testWorkDir); when(themeRoot.get()).thenReturn(testWorkDir);
final ThemeReconciler themeReconciler = final ThemeReconciler themeReconciler =
new ThemeReconciler(extensionClient, themeRoot, systemVersionSupplier); new ThemeReconciler(extensionClient, themeRoot, systemVersionSupplier,
templateEngineManager);
final int[] retryFlags = {0}; final int[] retryFlags = {0};
when(extensionClient.fetch(eq(Setting.class), eq("theme-test-setting"))) when(extensionClient.fetch(eq(Setting.class), eq("theme-test-setting")))
@ -196,7 +204,8 @@ class ThemeReconcilerTest {
when(themeRoot.get()).thenReturn(testWorkDir); when(themeRoot.get()).thenReturn(testWorkDir);
final ThemeReconciler themeReconciler = final ThemeReconciler themeReconciler =
new ThemeReconciler(extensionClient, themeRoot, systemVersionSupplier); new ThemeReconciler(extensionClient, themeRoot, systemVersionSupplier,
templateEngineManager);
Theme theme = fakeTheme(); Theme theme = fakeTheme();
theme.setStatus(null); theme.setStatus(null);
theme.getSpec().setRequires(">2.3.0"); theme.getSpec().setRequires(">2.3.0");