diff --git a/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/controller/LogController.java b/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/controller/LogController.java index e3b1f38..f3077ec 100644 --- a/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/controller/LogController.java +++ b/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/controller/LogController.java @@ -209,6 +209,18 @@ public class LogController { return ApiResponse.success(sourcemapService.listByAppKey(appKey)); } + @DeleteMapping("/sourcemaps/{id}") + public ApiResponse deleteSourcemap(@PathVariable Long id) { + sourcemapService.deleteById(id); + return ApiResponse.ok(); + } + + @PostMapping("/sourcemaps/prune-all") + public ApiResponse pruneAllSourcemaps() { + int deleted = sourcemapService.pruneAll(); + return ApiResponse.success("Pruned " + deleted + " records"); + } + // ── Webhooks ─────────────────────────────────────────────────────────────── @GetMapping("/webhooks") diff --git a/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/repository/LogSourcemapRepository.java b/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/repository/LogSourcemapRepository.java index 348d35e..d2e0c7a 100644 --- a/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/repository/LogSourcemapRepository.java +++ b/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/repository/LogSourcemapRepository.java @@ -28,6 +28,8 @@ public interface LogSourcemapRepository extends JpaRepository findByAppKeyAndPlatformAndBundleNameOrderByUploadedAtDesc( String appKey, String platform, String bundleName); + List findByAppKeyOrderByUploadedAtDesc(String appKey); + List findByAppKey(String appKey); void deleteByAppKey(String appKey); diff --git a/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/service/SourcemapService.java b/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/service/SourcemapService.java index 9eccfb4..66f3cb1 100644 --- a/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/service/SourcemapService.java +++ b/xuqm-bugcollect-service/src/main/java/com/xuqm/bugcollect/service/SourcemapService.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; @Service public class SourcemapService { @@ -208,12 +209,46 @@ public class SourcemapService { } } + /** One-time / admin: apply the retention policy to all existing records. Returns deleted count. */ + @Transactional + public int pruneAll() { + List all = sourcemapRepository.findAll(); + long before = all.size(); + + record VersionKey(String appKey, String platform, String bundleName, String appVersion) {} + Set versionKeys = all.stream() + .map(e -> new VersionKey(e.getAppKey(), e.getPlatform(), e.getBundleName(), e.getAppVersion())) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + for (VersionKey key : versionKeys) { + pruneSourcemaps(key.appKey(), key.platform(), key.appVersion(), key.bundleName()); + } + + long after = sourcemapRepository.count(); + int deleted = (int) (before - after); + log.info("pruneAll: scanned {} records, deleted {}", before, deleted); + return deleted; + } + public String readSourceMapContent(String storageKey) throws IOException { return Files.readString(Paths.get(storageKey)); } + @Transactional + public void deleteById(Long id) { + sourcemapRepository.findById(id).ifPresent(entity -> { + try { + Files.deleteIfExists(Paths.get(entity.getStorageKey())); + } catch (IOException e) { + log.warn("Could not delete sourcemap file {}: {}", entity.getStorageKey(), e.getMessage()); + } + sourcemapRepository.delete(entity); + log.info("Sourcemap deleted: id={} storageKey={}", id, entity.getStorageKey()); + }); + } + public List listByAppKey(String appKey) { - return sourcemapRepository.findByAppKey(appKey) + return sourcemapRepository.findByAppKeyOrderByUploadedAtDesc(appKey) .stream() .map(e -> new SourcemapInfo( e.getId(), e.getAppKey(), e.getPlatform(),