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 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); PrintTaskEntity getTaskById(Integer id);
List<PrinterResp> listByScenicId(@Param("scenicId") Long scenicId); List<PrinterResp> listByScenicId(@Param("scenicId") Long scenicId);
@@ -51,4 +55,4 @@ public interface PrinterMapper {
void updateUserPhotoListToPrinter(Long memberId, Long scenicId, Integer printerId); void updateUserPhotoListToPrinter(Long memberId, Long scenicId, Integer printerId);
List<MemberPrintResp> listRelationByOrderId(Long orderId); List<MemberPrintResp> listRelationByOrderId(Long orderId);
} }

View File

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

View File

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