feat(printer): 实现任务状态的原子性更新与同步锁机制

- 添加 compareAndSetTaskStatus 方法以支持基于期望状态的任务更新
- 引入 ReentrantLock 实现任务同步处理,防止并发冲突
- 在 XML 映射文件中定义 compareAndSetTaskStatus 的 SQL 更新语句
- 定义任务状态常量:TASK_STATUS_PENDING 和 TASK_STATUS_PROCESSING
- 优化任务获取逻辑,确保任务状态在处理前正确更新为 PROCESSING
This commit is contained in:
2025-10-23 21:24:58 +08:00
parent 3f8b911e6f
commit bed3a4e3c9
3 changed files with 36 additions and 7 deletions

View File

@@ -28,6 +28,10 @@ public interface PrinterMapper {
int updateTaskStatus(@Param("id") Integer id, @Param("status") Integer status);
int compareAndSetTaskStatus(@Param("id") Integer id,
@Param("expectStatus") Integer expectStatus,
@Param("newStatus") Integer newStatus);
PrintTaskEntity getTaskById(Integer id);
List<PrinterResp> listByScenicId(@Param("scenicId") Long scenicId);
@@ -51,4 +55,4 @@ public interface PrinterMapper {
void updateUserPhotoListToPrinter(Long memberId, Long scenicId, Integer printerId);
List<MemberPrintResp> listRelationByOrderId(Long orderId);
}
}

View File

@@ -69,6 +69,8 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@Slf4j
@@ -151,11 +153,26 @@ public class PrinterServiceImpl implements PrinterService {
printer.setPrinters(printersStr);
printerMapper.update(printer);
}
PrintTaskResp task = printerMapper.findTaskByPrinterId(printer.getId());
if (task == null) {
return Collections.emptyList();
syncTaskLock.lock();
try {
while (true) {
PrintTaskResp task = printerMapper.findTaskByPrinterId(printer.getId());
if (task == null) {
return Collections.emptyList();
}
int updatedRows = printerMapper.compareAndSetTaskStatus(
task.getId(),
TASK_STATUS_PENDING,
TASK_STATUS_PROCESSING
);
if (updatedRows == 1) {
task.setStatus(TASK_STATUS_PROCESSING);
return Collections.singletonList(task);
}
}
} finally {
syncTaskLock.unlock();
}
return Collections.singletonList(task);
}
@Override
@@ -427,6 +444,9 @@ public class PrinterServiceImpl implements PrinterService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String USER_PHOTO_LIST_TO_PRINTER = "USER_PHOTO_LIST_TO_PRINTER:";
private static final int TASK_STATUS_PENDING = 0;
private static final int TASK_STATUS_PROCESSING = 3;
private final Lock syncTaskLock = new ReentrantLock();
@Override
public void setUserIsBuyItem(Long memberId, Long id, Long orderId) {
@@ -550,4 +570,4 @@ public class PrinterServiceImpl implements PrinterService {
printTaskMapper.insertTask(task);
});
}
}
}

View File

@@ -152,6 +152,11 @@
<update id="updateTaskStatus">
UPDATE print_task SET status = #{status}, update_time = NOW() WHERE id = #{id}
</update>
<update id="compareAndSetTaskStatus">
UPDATE print_task
SET status = #{newStatus}, update_time = NOW()
WHERE id = #{id} AND status = #{expectStatus}
</update>
<update id="setPhotoCropped">
UPDATE member_print SET crop_url = #{url}, update_time = NOW(), print_url = null WHERE id = #{id}
</update>
@@ -172,4 +177,4 @@
<delete id="deleteUserPhoto">
DELETE FROM member_print WHERE member_id = #{memberId} AND scenic_id = #{scenicId} AND id = #{relationId} LIMIT 1;
</delete>
</mapper>
</mapper>