From 082ab489a3bd1fe79b5b0d3d189b2a9964e41a1b Mon Sep 17 00:00:00 2001 From: dongmucat <1127093059@qq.com> Date: Tue, 28 Jul 2026 11:06:14 +0800 Subject: [PATCH] fix(search): refresh index after version yank Signed-off-by: dongmucat <1127093059@qq.com> --- .../event/SearchIndexEventListener.java | 7 +++++ .../PostgresSearchRebuildService.java | 10 ++++++- .../event/SearchIndexEventListenerTest.java | 21 +++++++++++++++ .../PostgresSearchRebuildServiceTest.java | 26 +++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/event/SearchIndexEventListener.java b/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/event/SearchIndexEventListener.java index b0fcee58..098e1231 100644 --- a/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/event/SearchIndexEventListener.java +++ b/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/event/SearchIndexEventListener.java @@ -2,6 +2,7 @@ package com.iflytek.skillhub.search.event; import com.iflytek.skillhub.domain.event.SkillPublishedEvent; import com.iflytek.skillhub.domain.event.SkillStatusChangedEvent; +import com.iflytek.skillhub.domain.event.SkillVersionYankedEvent; import com.iflytek.skillhub.domain.skill.SkillStatus; import com.iflytek.skillhub.search.SearchIndexService; import com.iflytek.skillhub.search.SearchRebuildService; @@ -32,6 +33,12 @@ public class SearchIndexEventListener { searchRebuildService.rebuildBySkill(event.skillId()); } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + @Async("skillhubEventExecutor") + public void onSkillVersionYanked(SkillVersionYankedEvent event) { + searchRebuildService.rebuildBySkill(event.skillId()); + } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) @Async("skillhubEventExecutor") public void onSkillStatusChanged(SkillStatusChangedEvent event) { diff --git a/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildService.java b/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildService.java index 97e2d560..f0e09856 100644 --- a/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildService.java +++ b/server/skillhub-search/src/main/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildService.java @@ -116,7 +116,12 @@ public class PostgresSearchRebuildService implements SearchRebuildService { return; } - toDocument(skillOpt.get()).ifPresent(searchIndexService::index); + Optional document = toDocument(skillOpt.get()); + if (document.isPresent()) { + searchIndexService.index(document.get()); + } else { + searchIndexService.remove(skillId); + } } private SearchIndexPayload buildSearchPayload(Skill skill) { @@ -269,6 +274,9 @@ public class PostgresSearchRebuildService implements SearchRebuildService { } private Optional toDocument(Skill skill) { + if (skill.getLatestVersionId() == null) { + return Optional.empty(); + } Optional namespaceOpt = namespaceRepository.findById(skill.getNamespaceId()); if (namespaceOpt.isEmpty()) { return Optional.empty(); diff --git a/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/event/SearchIndexEventListenerTest.java b/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/event/SearchIndexEventListenerTest.java index 84a2b295..da0ecf55 100644 --- a/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/event/SearchIndexEventListenerTest.java +++ b/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/event/SearchIndexEventListenerTest.java @@ -2,11 +2,16 @@ package com.iflytek.skillhub.search.event; import com.iflytek.skillhub.domain.event.SkillPublishedEvent; import com.iflytek.skillhub.domain.event.SkillStatusChangedEvent; +import com.iflytek.skillhub.domain.event.SkillVersionYankedEvent; import com.iflytek.skillhub.domain.skill.SkillStatus; import com.iflytek.skillhub.search.SearchIndexService; import com.iflytek.skillhub.search.SearchRebuildService; import org.junit.jupiter.api.Test; +import java.lang.reflect.Method; +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -33,4 +38,20 @@ class SearchIndexEventListenerTest { verify(searchIndexService).remove(42L); } + + @Test + void yankedVersionShouldTriggerSkillRebuild() throws Exception { + SearchRebuildService searchRebuildService = mock(SearchRebuildService.class); + SearchIndexService searchIndexService = mock(SearchIndexService.class); + SearchIndexEventListener listener = new SearchIndexEventListener(searchRebuildService, searchIndexService); + + Method handler = Arrays.stream(SearchIndexEventListener.class.getDeclaredMethods()) + .filter(method -> Arrays.equals(method.getParameterTypes(), new Class[]{SkillVersionYankedEvent.class})) + .findFirst() + .orElse(null); + + assertThat(handler).isNotNull(); + handler.invoke(listener, new SkillVersionYankedEvent(42L, 100L, "admin-1")); + verify(searchRebuildService).rebuildBySkill(42L); + } } diff --git a/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildServiceTest.java b/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildServiceTest.java index 4abd1e63..806462ed 100644 --- a/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildServiceTest.java +++ b/server/skillhub-search/src/test/java/com/iflytek/skillhub/search/postgres/PostgresSearchRebuildServiceTest.java @@ -25,12 +25,38 @@ import java.util.List; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class PostgresSearchRebuildServiceTest { + @Test + void rebuildBySkill_shouldRemoveDocumentWhenNoPublishedVersionExists() { + SkillRepository skillRepository = mock(SkillRepository.class); + NamespaceRepository namespaceRepository = mock(NamespaceRepository.class); + SkillVersionRepository skillVersionRepository = mock(SkillVersionRepository.class); + SearchIndexService searchIndexService = mock(SearchIndexService.class); + + Skill skill = new Skill(7L, "pending-only", "owner-1", SkillVisibility.NAMESPACE_ONLY); + setField(skill, "id", 42L); + when(skillRepository.findById(42L)).thenReturn(Optional.of(skill)); + + PostgresSearchRebuildService service = newService( + skillRepository, + namespaceRepository, + skillVersionRepository, + searchIndexService + ); + + service.rebuildBySkill(42L); + + verify(searchIndexService).remove(42L); + verify(searchIndexService, never()).index(any()); + } + @Test void rebuildBySkill_shouldIndexFrontmatterFieldsAndKeywordsWithoutBody() { SkillRepository skillRepository = mock(SkillRepository.class);