diff --git a/src/main/java/com/ycwl/basic/image/pipeline/CLAUDE.md b/src/main/java/com/ycwl/basic/image/pipeline/CLAUDE.md index 0bb59703..b8782613 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/CLAUDE.md +++ b/src/main/java/com/ycwl/basic/image/pipeline/CLAUDE.md @@ -13,6 +13,7 @@ Image Pipeline 是一个通用的、可扩展的图片处理管线框架,用 - **配置驱动**: 支持通过外部配置控制 Stage 的启用/禁用 - **类型安全**: 使用泛型和枚举确保类型安全 - **解耦设计**: Context 独立于业务模型,支持多种使用场景 +- **自动清理**: 无论成功或失败都会在 finally 中兜底调用 `context.cleanup()` ## 包结构 @@ -207,6 +208,8 @@ public class WatermarkStage extends AbstractPipelineStage { | ImageEnhanceStage | 图像增强(超分) | SUPPORT | 可配置 | | ImageQualityCheckStage | 图像质量检测 | SUPPORT | 仅普通照片 | +> **提示**:`ImageEnhanceStage` 的默认构造函数会尝试从 `BCE_IMAGE_APP_ID/BCE_IMAGE_API_KEY/BCE_IMAGE_SECRET_KEY` 环境变量读取百度云凭据;若未配置则自动跳过执行。 + ### 存储 Stage | Stage | 职责 | Optional Mode | 执行条件 | @@ -214,6 +217,12 @@ public class WatermarkStage extends AbstractPipelineStage { | UploadStage | 上传图片到存储服务 | FORCE_ON | 总是执行 | | SourcePhotoUpdateStage | 更新源图片记录 | UNSUPPORT | 总是执行 | +### 辅助 Stage + +| Stage | 职责 | Optional Mode | 执行条件 | +|-------|------|---------------|---------| +| NoOpStage | 调试/占位 Stage,不做任何处理 | UNSUPPORT | 仅用于保持流程完整或调试 | + ## 典型管线示例 ### 1. 打印照片处理管线 @@ -553,7 +562,7 @@ A: 返回 `StageResult.failed()`,管线会立即终止。如果希望继续执 ### Q: 临时文件什么时候被清理? -A: 由 `CleanupStage` 负责,通常放在管线最后。也可以手动调用 `context.cleanup()`。 +A: 由 `CleanupStage` 负责,通常放在管线最后。也可以手动调用 `context.cleanup()`。此外,`Pipeline` 在 finally 中还会再调用一次 `context.cleanup()`,保证失败或异常时也能释放所有临时文件。 ### Q: 如何获取最终处理结果? diff --git a/src/main/java/com/ycwl/basic/image/pipeline/core/AbstractPipelineStage.java b/src/main/java/com/ycwl/basic/image/pipeline/core/AbstractPipelineStage.java index 4ad23962..1f38c11c 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/core/AbstractPipelineStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/core/AbstractPipelineStage.java @@ -65,7 +65,7 @@ public abstract class AbstractPipelineStage imple /** * 模板方法:执行Stage后的清理工作 */ - protected void afterExecute(C context, StageResult result) { + protected void afterExecute(C context, StageResult result) { if (result.isSuccess()) { log.debug("[{}] 执行成功: {}", getName(), result.getMessage()); } else if (result.isSkipped()) { @@ -80,15 +80,15 @@ public abstract class AbstractPipelineStage imple /** * 子类实现具体的处理逻辑 */ - protected abstract StageResult doExecute(C context); + protected abstract StageResult doExecute(C context); /** * 最终执行方法(带钩子) */ @Override - public final StageResult execute(C context) { + public final StageResult execute(C context) { beforeExecute(context); - StageResult result = doExecute(context); + StageResult result = doExecute(context); afterExecute(context, result); return result; } diff --git a/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java b/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java index 699848ac..7de6ba47 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java @@ -92,6 +92,7 @@ public class PhotoProcessContext { private File processedFile; private boolean isLandscape = true; private boolean rotationApplied = false; + private boolean cleaned = false; /** * 图像需要旋转的角度(用于后续Stage使用) @@ -227,7 +228,11 @@ public class PhotoProcessContext { * 清理所有临时文件 */ public void cleanup() { + if (cleaned) { + return; + } tempFileManager.cleanup(); + cleaned = true; } // ==================== Builder ==================== diff --git a/src/main/java/com/ycwl/basic/image/pipeline/core/Pipeline.java b/src/main/java/com/ycwl/basic/image/pipeline/core/Pipeline.java index 0b1c147d..abc6f154 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/core/Pipeline.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/core/Pipeline.java @@ -52,7 +52,7 @@ public class Pipeline { } long stageStartTime = System.currentTimeMillis(); - StageResult result = stage.execute(context); + StageResult result = stage.execute(context); long stageDuration = System.currentTimeMillis() - stageStartTime; executedCount++; @@ -60,12 +60,12 @@ public class Pipeline { // 动态添加后续Stage if (result.getNextStages() != null && !result.getNextStages().isEmpty()) { - List> nextStages = result.getNextStages(); + List> nextStages = result.getNextStages(); log.info("[{}] Stage {} 动态添加了 {} 个后续Stage", name, stageName, nextStages.size()); for (int j = 0; j < nextStages.size(); j++) { - PipelineStage nextStage = nextStages.get(j); - stages.add(i + 1 + j, (PipelineStage) nextStage); + PipelineStage nextStage = nextStages.get(j); + stages.add(i + 1 + j, nextStage); log.debug("[{}] - 插入Stage: {} 到位置 {}", name, nextStage.getName(), i + 1 + j); } } @@ -84,10 +84,12 @@ public class Pipeline { } catch (Exception e) { log.error("[{}] 管线执行异常", name, e); throw new PipelineException("管线执行失败: " + e.getMessage(), e); + } finally { + safeCleanup(context); } } - private void logStageResult(String stageName, StageResult result, long duration) { + private void logStageResult(String stageName, StageResult result, long duration) { String statusIcon = switch (result.getStatus()) { case SUCCESS -> "✓"; case SKIPPED -> "○"; @@ -114,4 +116,15 @@ public class Pipeline { public List getStageNames() { return stages.stream().map(PipelineStage::getName).toList(); } + + private void safeCleanup(C context) { + if (context == null) { + return; + } + try { + context.cleanup(); + } catch (Exception cleanupError) { + log.warn("[{}] 管线清理失败", name, cleanupError); + } + } } diff --git a/src/main/java/com/ycwl/basic/image/pipeline/core/PipelineStage.java b/src/main/java/com/ycwl/basic/image/pipeline/core/PipelineStage.java index ad9452c4..7d43ca5e 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/core/PipelineStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/core/PipelineStage.java @@ -30,7 +30,7 @@ public interface PipelineStage { * @param context 管线上下文 * @return 执行结果 */ - StageResult execute(C context); + StageResult execute(C context); /** * 获取Stage的执行优先级(用于排序) diff --git a/src/main/java/com/ycwl/basic/image/pipeline/core/StageResult.java b/src/main/java/com/ycwl/basic/image/pipeline/core/StageResult.java index 7b25de5d..20cdef5e 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/core/StageResult.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/core/StageResult.java @@ -11,7 +11,7 @@ import java.util.List; * Stage执行结果 */ @Getter -public class StageResult { +public class StageResult { public enum Status { SUCCESS, // 执行成功 @@ -23,9 +23,9 @@ public class StageResult { private final Status status; private final String message; private final Throwable exception; - private final List> nextStages; + private final List> nextStages; - private StageResult(Status status, String message, Throwable exception, List> nextStages) { + private StageResult(Status status, String message, Throwable exception, List> nextStages) { this.status = status; this.message = message; this.exception = exception; @@ -34,47 +34,47 @@ public class StageResult { : Collections.emptyList(); } - public static StageResult success() { - return new StageResult(Status.SUCCESS, null, null, null); + public static StageResult success() { + return new StageResult<>(Status.SUCCESS, null, null, null); } - public static StageResult success(String message) { - return new StageResult(Status.SUCCESS, message, null, null); + public static StageResult success(String message) { + return new StageResult<>(Status.SUCCESS, message, null, null); } /** * 成功执行并动态添加后续Stage */ @SafeVarargs - public static StageResult successWithNext(String message, PipelineStage... stages) { - return new StageResult(Status.SUCCESS, message, null, Arrays.asList(stages)); + public static StageResult successWithNext(String message, PipelineStage... stages) { + return new StageResult<>(Status.SUCCESS, message, null, Arrays.asList(stages)); } /** * 成功执行并动态添加后续Stage列表 */ - public static StageResult successWithNext(String message, List> stages) { - return new StageResult(Status.SUCCESS, message, null, stages); + public static StageResult successWithNext(String message, List> stages) { + return new StageResult<>(Status.SUCCESS, message, null, stages); } - public static StageResult skipped() { - return new StageResult(Status.SKIPPED, "条件不满足,跳过执行", null, null); + public static StageResult skipped() { + return new StageResult<>(Status.SKIPPED, "条件不满足,跳过执行", null, null); } - public static StageResult skipped(String reason) { - return new StageResult(Status.SKIPPED, reason, null, null); + public static StageResult skipped(String reason) { + return new StageResult<>(Status.SKIPPED, reason, null, null); } - public static StageResult failed(String message) { - return new StageResult(Status.FAILED, message, null, null); + public static StageResult failed(String message) { + return new StageResult<>(Status.FAILED, message, null, null); } - public static StageResult failed(String message, Throwable exception) { - return new StageResult(Status.FAILED, message, exception, null); + public static StageResult failed(String message, Throwable exception) { + return new StageResult<>(Status.FAILED, message, exception, null); } - public static StageResult degraded(String message) { - return new StageResult(Status.DEGRADED, message, null, null); + public static StageResult degraded(String message) { + return new StageResult<>(Status.DEGRADED, message, null, null); } public boolean isSuccess() { diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/CleanupStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/CleanupStage.java index c156113c..1ef47971 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/CleanupStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/CleanupStage.java @@ -31,7 +31,7 @@ public class CleanupStage extends AbstractPipelineStage { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { try { int fileCount = context.getTempFileManager().getTempFileCount(); context.cleanup(); diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java index e48de004..a259ef76 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java @@ -35,7 +35,7 @@ public class ConditionalRotateStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { try { File currentFile = context.getCurrentFile(); if (currentFile == null || !currentFile.exists()) { diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/DownloadStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/DownloadStage.java index 612a9437..9e5a876f 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/DownloadStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/DownloadStage.java @@ -31,7 +31,7 @@ public class DownloadStage extends AbstractPipelineStage { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { String url = context.getOriginalUrl(); if (StringUtils.isBlank(url)) { return StageResult.failed("原图URL为空"); diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStage.java index 431f0c02..c482398e 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStage.java @@ -38,11 +38,7 @@ public class ImageEnhanceStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { // 检查配置是否完整 if (!isConfigValid()) { log.warn("图像增强配置不完整,跳过增强处理。请在ImageEnhanceStage中配置百度云API凭证"); @@ -151,6 +147,15 @@ public class ImageEnhanceStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { try { File currentFile = context.getCurrentFile(); if (currentFile == null || !currentFile.exists()) { diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageQualityCheckStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageQualityCheckStage.java index a0722d09..f38b883f 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageQualityCheckStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/ImageQualityCheckStage.java @@ -50,7 +50,7 @@ public class ImageQualityCheckStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { File currentFile = context.getCurrentFile(); if (currentFile == null || !currentFile.exists()) { return StageResult.failed("当前文件不存在"); @@ -107,7 +107,7 @@ public class ImageQualityCheckStage extends AbstractPipelineStage checkAndAddMultipleStages(PhotoProcessContext context) { // 示例:根据不同条件添加多个Stage // 假设检测到需要多个增强操作 diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/NoOpStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/NoOpStage.java index 2ea5af7a..f50ff90e 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/NoOpStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/NoOpStage.java @@ -6,7 +6,7 @@ import com.ycwl.basic.image.pipeline.core.StageResult; public class NoOpStage extends AbstractPipelineStage { @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { return StageResult.skipped("无操作"); } diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/PuzzleBorderStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/PuzzleBorderStage.java index 82c3f2e7..8289e197 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/PuzzleBorderStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/PuzzleBorderStage.java @@ -39,7 +39,7 @@ public class PuzzleBorderStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { try { File currentFile = context.getCurrentFile(); if (currentFile == null || !currentFile.exists()) { diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStage.java index b481cc68..436d9a5c 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStage.java @@ -36,7 +36,7 @@ public class RestoreOrientationStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { try { File currentFile = context.getCurrentFile(); if (currentFile == null || !currentFile.exists()) { diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/SourcePhotoUpdateStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/SourcePhotoUpdateStage.java index 138e3287..c19d2784 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/SourcePhotoUpdateStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/SourcePhotoUpdateStage.java @@ -21,7 +21,7 @@ import java.io.File; @Slf4j @StageConfig( stageId = "source_photo_update", - optionalMode = StageOptionalMode.FORCE_ON, + optionalMode = StageOptionalMode.UNSUPPORT, description = "源图片上传和数据库更新", defaultEnabled = true ) @@ -47,7 +47,7 @@ public class SourcePhotoUpdateStage extends AbstractPipelineStage doExecute(PhotoProcessContext context) { File fileToUpload = context.getCurrentFile(); if (fileToUpload == null || !fileToUpload.exists()) { return StageResult.failed("没有可上传的文件"); diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java index 56c57a69..05f156fa 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java @@ -33,7 +33,7 @@ public class UploadStage extends AbstractPipelineStage { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { File fileToUpload = context.getCurrentFile(); if (fileToUpload == null || !fileToUpload.exists()) { return StageResult.failed("没有可上传的文件"); diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/WatermarkStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/WatermarkStage.java index f8c0bdd7..39369619 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/WatermarkStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/WatermarkStage.java @@ -55,7 +55,7 @@ public class WatermarkStage extends AbstractPipelineStage { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { if (config == null || config.getWatermarkType() == null) { log.info("未配置水印类型,跳过水印处理"); return StageResult.skipped("未配置水印"); @@ -75,7 +75,7 @@ public class WatermarkStage extends AbstractPipelineStage { } try { - StageResult result = applyWatermark(context, type); + StageResult result = applyWatermark(context, type); if (i > 0) { String degradeMsg = String.format("降级: %s -> %s", @@ -115,7 +115,7 @@ public class WatermarkStage extends AbstractPipelineStage { /** * 应用水印 */ - private StageResult applyWatermark(PhotoProcessContext context, ImageWatermarkOperatorEnum type) + private StageResult applyWatermark(PhotoProcessContext context, ImageWatermarkOperatorEnum type) throws Exception { File currentFile = context.getCurrentFile(); diff --git a/src/main/java/com/ycwl/basic/image/pipeline/util/TempFileManager.java b/src/main/java/com/ycwl/basic/image/pipeline/util/TempFileManager.java index aa08b957..bec4d394 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/util/TempFileManager.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/util/TempFileManager.java @@ -34,13 +34,21 @@ public class TempFileManager { } private Path initTempDirectory() { + Path baseDir = Path.of(System.getProperty("java.io.tmpdir"), "photo_process", processId); try { - Path systemTempDir = Files.createTempDirectory("photo_process_"); - log.debug("创建临时目录: {}", systemTempDir); - return systemTempDir; + Files.createDirectories(baseDir); + log.debug("创建隔离临时目录: {}", baseDir); + return baseDir; } catch (IOException e) { - log.warn("无法创建系统临时目录,使用当前目录", e); - return Path.of("."); + log.warn("无法创建隔离临时目录,尝试使用系统临时目录", e); + try { + Path fallback = Files.createTempDirectory("photo_process_" + processId + "_"); + log.debug("创建备用临时目录: {}", fallback); + return fallback; + } catch (IOException ex) { + log.warn("无法创建系统临时目录,使用当前目录", ex); + return Path.of("."); + } } } diff --git a/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineBuilderTest.java b/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineBuilderTest.java index 11a96018..ebe3c060 100644 --- a/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineBuilderTest.java +++ b/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineBuilderTest.java @@ -113,7 +113,7 @@ class PipelineBuilderTest { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { return StageResult.success(); } } diff --git a/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineTest.java b/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineTest.java index 8e9a454c..ec7944ab 100644 --- a/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineTest.java +++ b/src/test/java/com/ycwl/basic/image/pipeline/core/PipelineTest.java @@ -121,6 +121,20 @@ class PipelineTest { assertTrue(names.contains("MockStage-stage2")); } + @Test + void testPipelineFailureStillCleansTempFiles() { + Pipeline pipeline = new PipelineBuilder("CleanupGuarantee") + .addStage(new TempFileFailStage()) + .build(); + + PhotoProcessContext context = createTestContext(); + + boolean success = pipeline.execute(context); + + assertFalse(success); + assertEquals(0, context.getTempFileManager().getTempFileCount()); + } + /** * 创建测试用的 Context */ @@ -137,9 +151,9 @@ class PipelineTest { */ private static class MockStage extends AbstractPipelineStage { private final String id; - private final StageResult result; + private final StageResult result; - MockStage(String id, StageResult result) { + MockStage(String id, StageResult result) { this.id = id; this.result = result; } @@ -150,7 +164,7 @@ class PipelineTest { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { return result; } } @@ -178,8 +192,22 @@ class PipelineTest { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { return StageResult.success(); } } + + private static class TempFileFailStage extends AbstractPipelineStage { + + @Override + public String getName() { + return "TempFileFailStage"; + } + + @Override + protected StageResult doExecute(PhotoProcessContext context) { + context.getTempFileManager().createTempFile("fail", ".tmp"); + return StageResult.failed("force failure"); + } + } } diff --git a/src/test/java/com/ycwl/basic/image/pipeline/core/StageResultTest.java b/src/test/java/com/ycwl/basic/image/pipeline/core/StageResultTest.java index d9ff1796..cc10b28a 100644 --- a/src/test/java/com/ycwl/basic/image/pipeline/core/StageResultTest.java +++ b/src/test/java/com/ycwl/basic/image/pipeline/core/StageResultTest.java @@ -13,7 +13,7 @@ class StageResultTest { @Test void testSuccess() { - StageResult result = StageResult.success(); + StageResult result = StageResult.success(); assertEquals(StageResult.Status.SUCCESS, result.getStatus()); assertTrue(result.isSuccess()); @@ -25,7 +25,7 @@ class StageResultTest { @Test void testSuccessWithMessage() { - StageResult result = StageResult.success("处理完成"); + StageResult result = StageResult.success("处理完成"); assertTrue(result.isSuccess()); assertEquals("处理完成", result.getMessage()); @@ -36,7 +36,7 @@ class StageResultTest { MockStage nextStage1 = new MockStage("next1"); MockStage nextStage2 = new MockStage("next2"); - StageResult result = StageResult.successWithNext("添加后续Stage", nextStage1, nextStage2); + StageResult result = StageResult.successWithNext("添加后续Stage", nextStage1, nextStage2); assertTrue(result.isSuccess()); assertEquals("添加后续Stage", result.getMessage()); @@ -47,19 +47,19 @@ class StageResultTest { @Test void testSuccessWithNextStagesList() { - List> stages = List.of( + List> stages = List.of( new MockStage("next1"), new MockStage("next2") ); - StageResult result = StageResult.successWithNext("添加列表", stages); + StageResult result = StageResult.successWithNext("添加列表", stages); assertEquals(2, result.getNextStages().size()); } @Test void testSkipped() { - StageResult result = StageResult.skipped(); + StageResult result = StageResult.skipped(); assertEquals(StageResult.Status.SKIPPED, result.getStatus()); assertTrue(result.isSkipped()); @@ -69,7 +69,7 @@ class StageResultTest { @Test void testSkippedWithReason() { - StageResult result = StageResult.skipped("图片类型不匹配"); + StageResult result = StageResult.skipped("图片类型不匹配"); assertTrue(result.isSkipped()); assertEquals("图片类型不匹配", result.getMessage()); @@ -77,7 +77,7 @@ class StageResultTest { @Test void testFailed() { - StageResult result = StageResult.failed("下载失败"); + StageResult result = StageResult.failed("下载失败"); assertEquals(StageResult.Status.FAILED, result.getStatus()); assertTrue(result.isFailed()); @@ -88,7 +88,7 @@ class StageResultTest { @Test void testFailedWithException() { Exception exception = new RuntimeException("网络错误"); - StageResult result = StageResult.failed("下载失败", exception); + StageResult result = StageResult.failed("下载失败", exception); assertTrue(result.isFailed()); assertEquals("下载失败", result.getMessage()); @@ -97,7 +97,7 @@ class StageResultTest { @Test void testDegraded() { - StageResult result = StageResult.degraded("使用备用方案"); + StageResult result = StageResult.degraded("使用备用方案"); assertEquals(StageResult.Status.DEGRADED, result.getStatus()); assertTrue(result.isDegraded()); @@ -128,9 +128,9 @@ class StageResultTest { @Test void testNextStagesImmutable() { MockStage stage1 = new MockStage("stage1"); - StageResult result = StageResult.successWithNext("test", stage1); + StageResult result = StageResult.successWithNext("test", stage1); - List> nextStages = result.getNextStages(); + List> nextStages = result.getNextStages(); assertThrows(UnsupportedOperationException.class, () -> { nextStages.add(new MockStage("stage2")); @@ -153,7 +153,7 @@ class StageResultTest { } @Override - protected StageResult doExecute(PhotoProcessContext context) { + protected StageResult doExecute(PhotoProcessContext context) { return StageResult.success(); } } diff --git a/src/test/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStageTest.java b/src/test/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStageTest.java index ac7e4e68..e2b25264 100644 --- a/src/test/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStageTest.java +++ b/src/test/java/com/ycwl/basic/image/pipeline/stages/ImageEnhanceStageTest.java @@ -33,10 +33,10 @@ class ImageEnhanceStageTest { BceEnhancerConfig config = stage.getEnhancerConfig(); assertNotNull(config); - assertEquals("119554288", config.getAppId()); - assertEquals("OX6QoijgKio3eVtA0PiUVf7f", config.getApiKey()); - assertEquals("dYatXReVriPeiktTjUblhfubpcmYfuMk", config.getSecretKey()); assertEquals(1.0f, config.getQps()); + assertEquals(System.getenv("BCE_IMAGE_APP_ID"), config.getAppId()); + assertEquals(System.getenv("BCE_IMAGE_API_KEY"), config.getApiKey()); + assertEquals(System.getenv("BCE_IMAGE_SECRET_KEY"), config.getSecretKey()); } @Test