NfttStatusMaintenanceTask.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package modules.nftt;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.jfinal.kit.StrKit;
  4. import common.jfinal.AppConfig;
  5. import common.model.Nftt;
  6. import common.utils.bsn.BsnSDK;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import java.util.List;
  10. import java.util.concurrent.TimeUnit;
  11. public class NfttStatusMaintenanceTask implements Runnable {
  12. private static final Logger LOGGER = LoggerFactory.getLogger(NfttStatusMaintenanceTask.class);
  13. // 任务是否应该停止的标志
  14. private volatile boolean running = true; // 使用 volatile 确保多线程可见性
  15. public NfttStatusMaintenanceTask() {
  16. LOGGER.info("NftStatusMaintenanceTask 实例已创建。");
  17. }
  18. @Override
  19. public void run() {
  20. LOGGER.info("NftStatusMaintenanceTask 后台任务开始运行...");
  21. while (running) { // 循环直到收到停止指令
  22. try {
  23. // 每次循环后休眠一段时间,避免CPU空转,并控制检查频率
  24. Thread.sleep(TimeUnit.SECONDS.toMillis(10)); // 每 10 秒检查一次
  25. // 只处理已支付但未确权的
  26. String sql = "SELECT * FROM t_nftt WHERE bsn_token_id IS NULL";
  27. flushNftStatus(Nftt.dao.find(sql));
  28. } catch (InterruptedException e) {
  29. LOGGER.warn("NftStatusMaintenanceTask 因中断而停止。");
  30. Thread.currentThread().interrupt(); // 重新设置中断状态
  31. running = false; // 退出循环
  32. } catch (Exception e) {
  33. // 捕获所有其他异常,记录日志,但保持线程继续运行
  34. LOGGER.error("NftStatusMaintenanceTask 执行异常: {}", e.getMessage(), e);
  35. // 可以在这里添加告警,或在短时间后重试
  36. try {
  37. Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // 发生错误时短暂休眠,避免错误日志刷屏
  38. } catch (InterruptedException ie) {
  39. Thread.currentThread().interrupt();
  40. running = false;
  41. }
  42. }
  43. }
  44. LOGGER.info("NftStatusMaintenanceTask 后台任务已停止运行。");
  45. }
  46. private void flushNftStatus(List<Nftt> list) throws InterruptedException {
  47. // 遍历列表,处理 BSN 状态更新逻辑
  48. // 这个逻辑会影响分页查询的性能,特别是当 BsnSDK.search 是耗时操作时
  49. // 建议将其移到异步处理或专门的同步任务中
  50. for (Nftt nftt : list) {
  51. // bsnTokenId 如果不为空,说明已经处理过上链结果,跳过
  52. if (StrKit.notBlank(nftt.getBsnTokenId())) {
  53. continue;
  54. }
  55. try {
  56. // 调用 BSN SDK 查询上链状态
  57. // 确保 BsnSDK.search 返回的是 JSONObject,且参数正确
  58. JSONObject searchObject = BsnSDK.search("DLTBH_NFT_" + nftt.getLong("id")); // 假设 id 是 Long 类型
  59. // 记录原始响应,便于调试
  60. nftt.set("bsn_status_json", searchObject.toJSONString()); // 假设字段名为 bsn_status_json
  61. // 不需要在这里立即 update(),可以在最后处理完所有状态后再批量更新,或在成功时更新
  62. // nftt.update(); // 暂时移除,避免频繁更新
  63. // 校验 BSN SDK 响应
  64. if (searchObject.getInteger("code") == null || searchObject.getInteger("code") != 0) {
  65. throw new RuntimeException("BSN API查询失败,返回值与预期不符或code不为0:" + searchObject.toJSONString());
  66. }
  67. JSONObject data = searchObject.getJSONObject("data");
  68. if (data == null) {
  69. throw new RuntimeException("BSN API响应数据为空:" + searchObject.toJSONString());
  70. }
  71. Integer status = data.getInteger("status");
  72. if (status == null) {
  73. throw new RuntimeException("BSN API响应状态字段缺失:" + searchObject.toJSONString());
  74. }
  75. if (status == 2) { // 假设 status == 2 表示上链失败
  76. nftt.set("bsn_token_id", "-1"); // 标记上链失败
  77. nftt.set("bsn_status_json", searchObject.toJSONString()); // 更新失败状态信息
  78. nftt.update(); // 立即更新失败状态
  79. throw new RuntimeException("BSN 上链失败,链上的错误:" + searchObject.toJSONString());
  80. }
  81. if (status == 1) { // 假设 status == 1 表示上链成功且有 tokenId
  82. String tokenId = data.getString("tokenId");
  83. if (StrKit.isBlank(tokenId)) {
  84. throw new RuntimeException("BSN 上链成功但 tokenId 为空:" + searchObject.toJSONString());
  85. }
  86. nftt.set("bsn_token_id", tokenId);
  87. nftt.set("bsn_status_json", searchObject.toJSONString()); // 更新成功状态信息
  88. nftt.update(); // 立即更新成功状态
  89. AppConfig.LOGGER.error("查询并更新NFT {} 的BSN状态成功{}", nftt.getLong("id"), searchObject);
  90. }
  91. // 如果 status 是其他值,可能表示正在处理中,不更新 bsn_token_id
  92. } catch (Exception e) {
  93. // 记录错误日志,但通常不应该影响整个列表的返回
  94. AppConfig.LOGGER.error("查询并更新NFT {} 的BSN状态时出现问题:{}", nftt.getLong("id"), e.getMessage(), e);
  95. // 这里可以选择不throw,或者throw RuntimeException让上层捕获
  96. // 如果是服务故障,可能需要全局捕获并告警
  97. }
  98. }
  99. }
  100. }