diff --git a/mateclaw-server/src/main/java/vip/mate/wiki/controller/WikiHotCacheController.java b/mateclaw-server/src/main/java/vip/mate/wiki/controller/WikiHotCacheController.java new file mode 100644 index 00000000..aaca6ae2 --- /dev/null +++ b/mateclaw-server/src/main/java/vip/mate/wiki/controller/WikiHotCacheController.java @@ -0,0 +1,59 @@ +package vip.mate.wiki.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import vip.mate.common.result.R; +import vip.mate.wiki.hotcache.HotCacheUpdateReason; +import vip.mate.wiki.hotcache.HotCacheUpdateScheduler; +import vip.mate.wiki.hotcache.WikiHotCacheService; +import vip.mate.wiki.model.WikiHotCacheEntity; + +/** + * Operator endpoints for the KB hot cache: inspect the current snapshot, + * trigger a manual rebuild, or wipe the cache so the next event-driven + * rebuild starts from scratch. + * + *

Sits behind the standard JWT-protected {@code /api/v1} prefix. + */ +@RestController +@RequestMapping("/api/v1/wiki/hot-cache") +@RequiredArgsConstructor +@Tag(name = "Wiki Hot Cache", description = "Operator endpoints for the KB-level recent activity snapshot") +public class WikiHotCacheController { + + private final WikiHotCacheService service; + private final HotCacheUpdateScheduler scheduler; + + @Operation(summary = "Get the current hot cache snapshot for a KB", + description = "Returns null data if no rebuild has run yet.") + @GetMapping("/{kbId}") + public R get(@PathVariable Long kbId) { + return R.ok(service.findByKb(kbId).orElse(null)); + } + + @Operation(summary = "Schedule a manual rebuild of the hot cache", + description = "Async — the scheduler runs the LLM call on a virtual thread. " + + "MANUAL bypasses the debounce window so operator triggers always run. " + + "Poll GET to see progress.") + @PostMapping("/{kbId}/regenerate") + public R regenerate(@PathVariable Long kbId) { + scheduler.scheduleRebuild(kbId, HotCacheUpdateReason.MANUAL); + return R.ok(); + } + + @Operation(summary = "Soft-delete the hot cache row", + description = "The next event-driven rebuild will create a fresh row. " + + "Use this to clear a wedged cache without waiting for the staleness window.") + @DeleteMapping("/{kbId}") + public R reset(@PathVariable Long kbId) { + service.findByKb(kbId).ifPresent(row -> service.softDelete(row.getId())); + return R.ok(); + } +} diff --git a/mateclaw-server/src/main/java/vip/mate/wiki/hotcache/WikiHotCacheService.java b/mateclaw-server/src/main/java/vip/mate/wiki/hotcache/WikiHotCacheService.java index 89e0fc53..5c2c7e9f 100644 --- a/mateclaw-server/src/main/java/vip/mate/wiki/hotcache/WikiHotCacheService.java +++ b/mateclaw-server/src/main/java/vip/mate/wiki/hotcache/WikiHotCacheService.java @@ -46,4 +46,14 @@ public class WikiHotCacheService { public String getContentOrNull(Long kbId) { return findByKb(kbId).map(WikiHotCacheEntity::getContent).orElse(null); } + + /** + * Soft-deletes the row by id. The {@code deleted} column flips via + * the mapper's {@code @TableLogic} annotation, so the next event-driven + * rebuild will create a fresh row. + */ + public void softDelete(Long id) { + if (id == null) return; + mapper.deleteById(id); + } }