【解决todo】修改命名、方法返回、链式调用、显示保存、代码逻辑换货

This commit is contained in:
cherishsince 2024-06-11 15:32:57 +08:00
parent e781129dbe
commit 1ac1c007ad
4 changed files with 66 additions and 68 deletions

View File

@ -74,16 +74,18 @@ public class AiImageController {
@Operation(summary = "Midjourney 回调通知", description = "由 Midjourney Proxy 回调") @Operation(summary = "Midjourney 回调通知", description = "由 Midjourney Proxy 回调")
@PostMapping("/midjourney-notify") @PostMapping("/midjourney-notify")
@PermitAll @PermitAll
public CommonResult<Boolean> midjourneyNotify(@RequestBody MidjourneyNotifyReqVO notifyReqVO) { public void midjourneyNotify(@RequestBody MidjourneyNotifyReqVO notifyReqVO) {
return success(imageService.midjourneyNotify(notifyReqVO)); imageService.midjourneyNotify(notifyReqVO);
} }
@Operation(summary = "Midjourney Action", description = "例如说放大、缩小、U1、U2 等") @Operation(summary = "Midjourney Action", description = "例如说放大、缩小、U1、U2 等")
@GetMapping("/midjourney/action") @GetMapping("/midjourney/action")
// TODO @fanidcustomerId swagger 注解 @Parameter(name = "id", description = "图片id", example = "1")
@Parameter(name = "customId", description = "操作id", example = "MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862")
public CommonResult<Boolean> midjourneyAction(@RequestParam("id") Long imageId, public CommonResult<Boolean> midjourneyAction(@RequestParam("id") Long imageId,
@RequestParam("customId") String customId) { @RequestParam("customId") String customId) {
return success(imageService.midjourneyAction(getLoginUserId(), imageId, customId)); imageService.midjourneyAction(getLoginUserId(), imageId, customId);
return success(null);
} }
} }

View File

@ -103,7 +103,7 @@ public class AiImageDO extends BaseDO {
private MidjourneyNotifyReqVO response; private MidjourneyNotifyReqVO response;
/** /**
* mj 进度 * mj 进度(10%50%100%)
*/ */
private String progress; private String progress;

View File

@ -63,7 +63,7 @@ public interface AiImageService {
* @param notifyReqVO * @param notifyReqVO
* @return * @return
*/ */
Boolean midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO); void midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO);
/** /**
* 构建 midjourney - 更新对象 * 构建 midjourney - 更新对象
@ -82,5 +82,5 @@ public interface AiImageService {
* @param customId * @param customId
* @return * @return
*/ */
Boolean midjourneyAction(Long loginUserId, Long imageId, String customId); void midjourneyAction(Long loginUserId, Long imageId, String customId);
} }

View File

@ -134,49 +134,39 @@ public class AiImageServiceImpl implements AiImageService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long midjourneyImagine(Long userId, AiImageMidjourneyImagineReqVO req) { public Long midjourneyImagine(Long userId, AiImageMidjourneyImagineReqVO req) {
// TODO @fan1 2 应该放在一个 1 里面不然 = = 一个逻辑就显得有很多 1/2/3/4这么分的原因是方便阅读的时候容易理解 // 1构建 AiImageDO 保存
// 1构建 AiImageDO AiImageDO image = new AiImageDO()
// TODO @fan1aiImageDO 可以缩写成 image 更简洁2可以链式调用把相同的放在一行里这样更容易分组 .setUserId(userId)
AiImageDO aiImageDO = new AiImageDO(); .setPrompt(req.getPrompt())
aiImageDO.setUserId(userId); .setPlatform(AiPlatformEnum.MIDJOURNEY.getPlatform())
aiImageDO.setPrompt(req.getPrompt()); .setModel(req.getModel())
aiImageDO.setPlatform(AiPlatformEnum.MIDJOURNEY.getPlatform()); .setWidth(req.getWidth())
aiImageDO.setModel(req.getModel()); .setHeight(req.getHeight())
aiImageDO.setWidth(req.getWidth()); .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
aiImageDO.setHeight(req.getHeight()); imageMapper.insert(image);
aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
// 2保存 image
imageMapper.insert(aiImageDO);
// TODO @fan3 2 之间应该空一行因为这里是开始发起请求第三方是个单独的小块逻辑
// 3调用 MidjourneyProxy 提交任务 // 3调用 MidjourneyProxy 提交任务
// 3.1设置 midjourney 扩展参数
MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class); MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class);
imagineReqVO.setNotifyHook(midjourneyNotifyUrl); imagineReqVO.setNotifyHook(midjourneyNotifyUrl);
// 4设置 midjourney 扩展参数
imagineReqVO.setState(buildParams(req.getWidth(), imagineReqVO.setState(buildParams(req.getWidth(),
req.getHeight(), req.getVersion(), MidjourneyModelEnum.valueOfModel(req.getModel()))); req.getHeight(), req.getVersion(), MidjourneyModelEnum.valueOfModel(req.getModel())));
// 5提交绘画请求 // 3.2提交绘画请求
// TODO @fan5 这里失败的情况到底抛出异常还是 RespVO可以参考 OpenAI API 封装 // TODO @fan5 这里失败的情况到底抛出异常还是 RespVO可以参考 OpenAI API 封装
MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO); MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO);
// 6保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误))
// 4保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误))
if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) {
throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription()); throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription());
} }
// TODO @fan7 6 之间应该空一行这样最终这个逻辑就会有 2 个空行3 小块逻辑1插入2调用3更新 // 4.1更新 taskId 和参数
// 7构建 imageOptions 参数
// TODO @fan1链式调用2其实可以直接使用 AiImageMidjourneyImagineReqVO不用单独一个 options 类哈
MidjourneyImageOptions imageOptions = new MidjourneyImageOptions()
.setWidth(req.getWidth())
.setHeight(req.getHeight())
.setModel(req.getModel())
.setVersion(req.getVersion())
.setState(imagineReqVO.getState());
// 8更新 taskId 和参数
imageMapper.updateById(new AiImageDO() imageMapper.updateById(new AiImageDO()
.setId(aiImageDO.getId()) .setId(image.getId())
.setTaskId(submitRespVO.getResult()) .setTaskId(submitRespVO.getResult())
.setOptions(BeanUtil.beanToMap(imageOptions)) .setOptions(BeanUtil.beanToMap(req))
); );
return aiImageDO.getId(); return image.getId();
} }
@ -191,23 +181,21 @@ public class AiImageServiceImpl implements AiImageService {
imageMapper.deleteById(id); imageMapper.deleteById(id);
} }
// TODO @fan建议返回 void然后如果不存在就抛出异常哈
@Override @Override
public Boolean midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { public void midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) {
// 1根据 job id 查询关联的 image // 1根据 job id 查询关联的 image
AiImageDO image = imageMapper.selectByJobId(notifyReqVO.getId()); AiImageDO image = imageMapper.selectByJobId(notifyReqVO.getId());
if (image == null) { if (image == null) {
log.warn("midjourneyNotify 回调的 jobId 不存在! jobId: {}", notifyReqVO.getId()); log.warn("midjourneyNotify 回调的 jobId 不存在! jobId: {}", notifyReqVO.getId());
return false;
} }
// 2转换状态 // 2转换状态
AiImageDO updateImage = buildUpdateImage(image.getId(), notifyReqVO); AiImageDO updateImage = buildUpdateImage(image.getId(), notifyReqVO);
// 3更新 image 状态 // 3更新 image 状态
return imageMapper.updateById(updateImage) > 0; imageMapper.updateById(updateImage);
} }
public AiImageDO buildUpdateImage(Long imageId, MidjourneyNotifyReqVO notifyReqVO) { public AiImageDO buildUpdateImage(Long imageId, MidjourneyNotifyReqVO notifyReqVO) {
// 2转换状态 // 1转换状态
String imageStatus = null; String imageStatus = null;
MidjourneyTaskStatusEnum taskStatusEnum = MidjourneyTaskStatusEnum.valueOf(notifyReqVO.getStatus()); MidjourneyTaskStatusEnum taskStatusEnum = MidjourneyTaskStatusEnum.valueOf(notifyReqVO.getStatus());
if (MidjourneyTaskStatusEnum.SUCCESS == taskStatusEnum) { if (MidjourneyTaskStatusEnum.SUCCESS == taskStatusEnum) {
@ -215,7 +203,8 @@ public class AiImageServiceImpl implements AiImageService {
} else if (MidjourneyTaskStatusEnum.FAILURE == taskStatusEnum) { } else if (MidjourneyTaskStatusEnum.FAILURE == taskStatusEnum) {
imageStatus = AiImageStatusEnum.FAIL.getStatus(); imageStatus = AiImageStatusEnum.FAIL.getStatus();
} }
// 3上传图片
// 2上传图片
String filePath = null; String filePath = null;
if (!StrUtil.isBlank(notifyReqVO.getImageUrl())) { if (!StrUtil.isBlank(notifyReqVO.getImageUrl())) {
try { try {
@ -224,7 +213,8 @@ public class AiImageServiceImpl implements AiImageService {
log.warn("midjourneyNotify 图片上传失败! {} 异常:{}", notifyReqVO.getImageUrl(), ExceptionUtil.getMessage(e)); log.warn("midjourneyNotify 图片上传失败! {} 异常:{}", notifyReqVO.getImageUrl(), ExceptionUtil.getMessage(e));
} }
} }
// 4更新 image 状态
// 3更新 image 状态
return new AiImageDO() return new AiImageDO()
.setId(imageId) .setId(imageId)
.setStatus(imageStatus) .setStatus(imageStatus)
@ -235,55 +225,60 @@ public class AiImageServiceImpl implements AiImageService {
.setErrorMessage(notifyReqVO.getFailReason()); .setErrorMessage(notifyReqVO.getFailReason());
} }
// TODO @fan1不用返回 Boolean
@Override @Override
@Transactional(rollbackFor = Exception.class) // TODO @fan只操作一个 db不用事务哈 public void midjourneyAction(Long loginUserId, Long imageId, String customId) {
public Boolean midjourneyAction(Long loginUserId, Long imageId, String customId) {
// TODO @fan11 2可以写成 1.11.2都是在做校验2validateCustomId 可以直接抛出 AI_IMAGE_CUSTOM_ID_NOT_EXISTS 异常一般情况下validateXXX 都是失败抛出异常isXXXValid 返回 truefalse
// 1检查 image // 1检查 image
// TODO @fan1aiImageDO 缩写成 image AiImageDO image = validateImageExists(imageId);
AiImageDO aiImageDO = validateImageExists(imageId);
// 2检查 customId // 2检查 customId
if (!validateCustomId(customId, aiImageDO.getButtons())) { validateCustomId(customId, image.getButtons());
throw exception(AI_IMAGE_CUSTOM_ID_NOT_EXISTS);
}
// TODO @fan2 3 之间空一行
// 3调用 midjourney proxy // 3调用 midjourney proxy
MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.action( MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.action(
new MidjourneyActionReqVO() new MidjourneyActionReqVO()
.setCustomId(customId) .setCustomId(customId)
.setTaskId(aiImageDO.getTaskId()) .setTaskId(image.getTaskId())
.setNotifyHook(midjourneyNotifyUrl) .setNotifyHook(midjourneyNotifyUrl)
); );
// 6保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) // 4检查错误 code (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误))
if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) {
throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription()); throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription());
} }
// TODO 6 4 之间空一行
// 4新增 image 记录 // 5新增 image 记录(根据 image 新增一个)
AiImageDO newImage = BeanUtils.toBean(aiImageDO, AiImageDO.class); AiImageDO newImage = new AiImageDO();
// TODO @fan最好不要 copy 属性因为未来如果加属性可能会导致额外 copy 最好是 new 赋值下显示声明
// 4.1重置参数
newImage.setId(null); newImage.setId(null);
newImage.setUserId(image.getUserId());
newImage.setPrompt(image.getPrompt());
newImage.setPlatform(image.getPlatform());
newImage.setModel(image.getModel());
newImage.setWidth(image.getWidth());
newImage.setHeight(image.getHeight());
newImage.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); newImage.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
newImage.setPublicStatus(image.getPublicStatus());
newImage.setPicUrl(null); newImage.setPicUrl(null);
newImage.setResponse(null);
newImage.setProgress(null); newImage.setProgress(null);
newImage.setButtons(null);
newImage.setOptions(image.getOptions());
newImage.setResponse(image.getResponse());
newImage.setTaskId(submitRespVO.getResult()); newImage.setTaskId(submitRespVO.getResult());
newImage.setErrorMessage(null); newImage.setErrorMessage(null);
newImage.setButtons(null);
// 4.2保存数据库
imageMapper.insert(newImage); imageMapper.insert(newImage);
return Boolean.TRUE;
} }
private static boolean validateCustomId(String customId, List<MidjourneyNotifyReqVO.Button> buttons) { private static void validateCustomId(String customId, List<MidjourneyNotifyReqVO.Button> buttons) {
boolean isTrue = false;
for (MidjourneyNotifyReqVO.Button button : buttons) { for (MidjourneyNotifyReqVO.Button button : buttons) {
if (button.getCustomId().equals(customId)) { if (button.getCustomId().equals(customId)) {
return true; isTrue = true;
break;
} }
} }
return false; if (isTrue) {
throw exception(AI_IMAGE_CUSTOM_ID_NOT_EXISTS);
}
} }
private AiImageDO validateImageExists(Long id) { private AiImageDO validateImageExists(Long id) {
@ -304,6 +299,7 @@ public class AiImageServiceImpl implements AiImageService {
} }
// TODO @fan这个是不是应该放在 MJ API 的封装里面搞哈 // TODO @fan这个是不是应该放在 MJ API 的封装里面搞哈
/** /**
* 构建 Midjourney 自定义参数 * 构建 Midjourney 自定义参数
* *