From 6ba5a6efde6707150afee0a923895d44e8ae05ea Mon Sep 17 00:00:00 2001 From: liujiang <569804566@qq.com> Date: Sat, 25 Oct 2025 22:07:18 +0800 Subject: [PATCH] =?UTF-8?q?master=EF=BC=9A=E5=95=86=E5=93=81=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E5=8F=8A=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=88=B0ES=E8=B0=83=E6=95=B4=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xkt/migartion/GtAndFhbBizController.java | 6 - .../java/com/ruoyi/quartz/task/XktTask.java | 110 +++++++++++------- sql/ry_20240629.sql | 1 - .../service/impl/StoreProductServiceImpl.java | 45 ++----- 4 files changed, 80 insertions(+), 82 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndFhbBizController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndFhbBizController.java index 57889c5a6..7afecfafc 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndFhbBizController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndFhbBizController.java @@ -82,12 +82,6 @@ public class GtAndFhbBizController extends BaseController { final IPictureService pictureService; final FsNotice fsNotice; - - // TODO 提供导出测试环境数据的接口,不然迁移到生产还要重新来一遍 - // TODO 提供导出测试环境数据的接口,不然迁移到生产还要重新来一遍 - // TODO 提供导出测试环境数据的接口,不然迁移到生产还要重新来一遍 - - /** * step1 */ diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java index 62b114a6b..5c060fc40 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java @@ -10,6 +10,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import co.elastic.clients.elasticsearch.core.BulkResponse; import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.constant.CacheConstants; @@ -438,6 +439,9 @@ public class XktTask { // 先删除所有的商品标签,保证数据唯一性 List existList = this.dailyProdTagMapper.selectList(new LambdaQueryWrapper() .eq(DailyProdTag::getDelFlag, Constants.UNDELETED)); + // 已存在于ES中的标签 + Map> existProdTagMap = CollectionUtils.isEmpty(existList) ? new HashMap<>() + :existList.stream().collect(Collectors.toMap(DailyProdTag::getStoreProdId, x -> new ArrayList<>(), (s1, s2) -> s2)); if (CollectionUtils.isNotEmpty(existList)) { this.dailyProdTagMapper.deleteByIds(existList.stream().map(DailyProdTag::getId).collect(Collectors.toList())); } @@ -474,8 +478,16 @@ public class XktTask { return; } this.dailyProdTagMapper.insert(tagList); + // 最新的待更新的商品标签列表 + Map> tagMap = tagList.stream().collect(Collectors + .groupingBy(DailyProdTag::getStoreProdId, Collectors.mapping(DailyProdTag::getTag, Collectors.toList()))); + existProdTagMap.forEach((storeProdId, tags) -> { + if (!tagMap.containsKey(storeProdId)) { + tagMap.put(storeProdId, tags); + } + }); // 更新商品的标签到ES - this.updateESProdTags(tagList); + this.updateESProdTags(tagMap); } /** @@ -794,11 +806,17 @@ public class XktTask { try { // 调用bulk方法执行批量更新操作 BulkResponse bulkResponse = esClientWrapper.getEsClient().bulk(e -> e.index(Constants.ES_IDX_PRODUCT_INFO).operations(list)); - log.info("bulkResponse.result() = {}", bulkResponse.items()); - } catch (IOException | RuntimeException e) { - // 记录日志并抛出或处理异常 - log.error("向ES更新档口权重失败,商品ID: {}, 错误信息: {}", storeProdList.stream().map(StoreProduct::getId).collect(Collectors.toList()), e.getMessage()); - throw e; // 或者做其他补偿处理,比如异步重试 + log.info("定时任务,批量更新档口权重到 ES 成功的 id列表: {}", bulkResponse.items().stream().map(BulkResponseItem::id).collect(Collectors.toList())); + // 有哪些没执行成功的,需要发飞书通知 + List successIdList = bulkResponse.items().stream().map(BulkResponseItem::id).collect(Collectors.toList()); + List unExeIdList = storeProdList.stream().map(String::valueOf).filter(x -> !successIdList.contains(x)).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(unExeIdList)) { + fsNotice.sendMsg2DefaultChat("定时任务,批量更新档口权重到 ES 失败", "以下storeProdId未执行成功: " + unExeIdList); + } + } catch (Exception e) { + log.error("定时任务,批量更新档口权重到 ES 失败", e); + fsNotice.sendMsg2DefaultChat("全部失败,定时任务批量更新档口权重到 ES 失败", + storeProdList.stream().map(StoreProduct::getId).map(String::valueOf).collect(Collectors.joining(","))); } } @@ -922,17 +940,25 @@ public class XktTask { } // 执行批量插入 try { - BulkResponse response = esClientWrapper.getEsClient().bulk(b -> b.index(Constants.ES_IDX_PRODUCT_INFO).operations(bulkOperations)); - log.info("批量插入到 ES 成功,共处理 {} 条记录", response.items().size()); + BulkResponse bulkResponse = esClientWrapper.getEsClient().bulk(b -> b.index(Constants.ES_IDX_PRODUCT_INFO).operations(bulkOperations)); + log.info("定时发布商品,批量新增商品到 ES 成功的 id列表: {}", bulkResponse.items().stream().map(BulkResponseItem::id).collect(Collectors.toList())); + // 有哪些没执行成功的,需要发飞书通知 + List successIdList = bulkResponse.items().stream().map(BulkResponseItem::id).collect(Collectors.toList()); + List unExeIdList = unPublicList.stream().map(String::valueOf).filter(x -> !successIdList.contains(x)).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(unExeIdList)) { + fsNotice.sendMsg2DefaultChat("定时发布商品,批量新增商品到 ES 失败", "以下storeProdId未执行成功: " + unExeIdList); + } } catch (Exception e) { - log.error("批量插入到 ES 失败", e); + log.error("定时发布商品,批量新增商品到 ES 失败", e); + fsNotice.sendMsg2DefaultChat("定时发布商品,批量新增商品到 ES 失败", + unPublicList.stream().map(StoreProduct::getId).map(String::valueOf).collect(Collectors.joining(","))); } for (StoreProduct product : unPublicList) { List mainPicUrlList = mainPicMap.get(product.getId()); if (CollUtil.isEmpty(mainPicUrlList)) { return; } - this.sync2ImgSearchServer(product.getId(), mainPicUrlList, true); + this.sync2ImgSearchServer(product.getId(), mainPicUrlList); } } @@ -1534,26 +1560,35 @@ public class XktTask { /** * 更新商品的标签到ES * - * @param tagList 标签集合 - * @throws IOException + * @param prodTagMap 标签map */ - private void updateESProdTags(List tagList) throws IOException { + private void updateESProdTags(Map> prodTagMap) { // 构建一个批量数据集合 List list = new ArrayList<>(); - tagList.stream().collect(Collectors.groupingBy(DailyProdTag::getStoreProdId)) - .forEach((storeProdId, tags) -> { - // 构建部分文档更新请求 - list.add(new BulkOperation.Builder().update(u -> u - .action(a -> a.doc(new HashMap() {{ - put("tags", tags.stream().sorted(Comparator.comparing(x -> x.getType())).map(DailyProdTag::getTag).collect(Collectors.toList())); - }})) - .id(String.valueOf(storeProdId)) - .index(Constants.ES_IDX_PRODUCT_INFO)) - .build()); - }); - // 调用bulk方法执行批量更新操作 - BulkResponse bulkResponse = esClientWrapper.getEsClient().bulk(e -> e.index(Constants.ES_IDX_PRODUCT_INFO).operations(list)); - System.out.println("bulkResponse.items() = " + bulkResponse.items()); + prodTagMap.forEach((storeProdId, updateTags) -> { + // 构建部分文档更新请求 + list.add(new BulkOperation.Builder().update(u -> u + .action(a -> a.doc(new HashMap() {{ + put("tags", updateTags); + }})) + .id(String.valueOf(storeProdId)) + .index(Constants.ES_IDX_PRODUCT_INFO)) + .build()); + }); + try { + // 调用bulk方法执行批量更新操作 + BulkResponse bulkResponse = esClientWrapper.getEsClient().bulk(e -> e.index(Constants.ES_IDX_PRODUCT_INFO).operations(list)); + log.info("批量更新商品标签到 ES 成功的 id列表: {}", bulkResponse.items().stream().map(BulkResponseItem::id).collect(Collectors.toList())); + // 有哪些没执行成功的,需要发飞书通知 + List successIdList = bulkResponse.items().stream().map(BulkResponseItem::id).collect(Collectors.toList()); + List unExeIdList = prodTagMap.keySet().stream().map(String::valueOf).filter(x -> !successIdList.contains(x)).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(unExeIdList)) { + fsNotice.sendMsg2DefaultChat("定时任务批量更新商品标签到 ES 失败", "以下storeProdId未执行成功: " + unExeIdList); + } + } catch (Exception e) { + log.error("定时任务批量更新标签到 ES 失败", e); + fsNotice.sendMsg2DefaultChat("全部失败,定时任务批量更新商品标签到 ES 失败", prodTagMap.keySet().toString()); + } } /** @@ -1577,21 +1612,14 @@ public class XktTask { * * @param storeProductId * @param picKeys - * @param async */ - private void sync2ImgSearchServer(Long storeProductId, List picKeys, boolean async) { - if (async) { - ThreadUtil.execAsync(() -> { - ProductPicSyncResultDTO r = - pictureService.sync2ImgSearchServer(new ProductPicSyncDTO(storeProductId, picKeys)); - log.info("商品图片同步至搜图服务器: id: {}, result: {}", storeProductId, JSONUtil.toJsonStr(r)); - } - ); - } else { - ProductPicSyncResultDTO r = - pictureService.sync2ImgSearchServer(new ProductPicSyncDTO(storeProductId, picKeys)); - log.info("商品图片同步至搜图服务器: id: {}, result: {}", storeProductId, JSONUtil.toJsonStr(r)); - } + private void sync2ImgSearchServer(Long storeProductId, List picKeys) { + ThreadUtil.execAsync(() -> { + ProductPicSyncResultDTO r = + pictureService.sync2ImgSearchServer(new ProductPicSyncDTO(storeProductId, picKeys)); + log.info("商品图片同步至搜图服务器: id: {}, result: {}", storeProductId, JSONUtil.toJsonStr(r)); + } + ); } /** diff --git a/sql/ry_20240629.sql b/sql/ry_20240629.sql index 8fe0b6e0f..dd4531edf 100644 --- a/sql/ry_20240629.sql +++ b/sql/ry_20240629.sql @@ -45,7 +45,6 @@ INSERT INTO `advert` VALUES (45, 1, 'ENYmwRr7T1', 1, 1, 7, 1, 1, 3, 300.00, 3, 4 INSERT INTO `advert` VALUES (46, 1, 'KIMSCC0h48', 1, 1, 8, 1, 1, 1, 300.00, 3, 4, '22:00:00', 5, 123, '840*470', '不超过5.00M', NULL, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 22:56:27', '', '2025-08-13 22:56:27'); INSERT INTO `advert` VALUES (47, 1, 'iAHKrJlQSX', 1, 1, 9, 1, 1, 1, 300.00, 3, 4, '22:00:00', 2, 124, '840*470', '不超过5.00M', NULL, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 22:57:13', '', '2025-08-13 22:57:13'); INSERT INTO `advert` VALUES (48, 2, '3I8CDuP3mZ', 2, 1, 10, 1, 1, 2, 300.00, 3, 4, '22:00:00', 2, NULL, '', '', 2, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 22:57:41', '', '2025-08-13 22:57:41'); -INSERT INTO `advert` VALUES (49, 1, 'xgDyZoXlfh', 1, 1, 11, 1, 1, 1, 300.00, 3, 4, '22:00:00', 1, 125, '840*470', '不超过5.00M', NULL, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 22:58:29', '', '2025-08-13 22:58:29'); INSERT INTO `advert` VALUES (50, 1, 'cjHdgozRUw', 20, 1, 12, 1, 1, 2, 450.00, 3, 4, '22:00:00', 20, NULL, '', '', NULL, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 23:00:55', '', '2025-08-13 23:00:55'); INSERT INTO `advert` VALUES (51, 1, 'RNsmF98eoy', 1, 1, 13, 1, 1, 1, 300.00, 3, 4, '22:00:00', 1, 126, '840*470', '不超过5.00M', NULL, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 23:01:31', '', '2025-08-13 23:01:31'); INSERT INTO `advert` VALUES (52, 1, '1egXOizbf8', 1, 1, 14, 1, 1, 4, 750.00, 15, 4, '22:00:00', 10, NULL, '', '', NULL, NULL, NULL, NULL, NULL, 0, '0', '', '2025-08-13 23:04:07', '', '2025-08-13 23:04:07'); diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java index 9ccc7cb47..e580d853c 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java @@ -22,13 +22,12 @@ import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.core.page.Page; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.exception.user.CaptchaException; -import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.utils.AdValidator; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.HtmlValidator; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.framework.es.EsClientWrapper; +import com.ruoyi.framework.notice.fs.FsNotice; import com.ruoyi.framework.oss.OSSClientWrapper; import com.ruoyi.system.domain.dto.productCategory.ProdCateDTO; import com.ruoyi.xkt.domain.*; @@ -109,6 +108,7 @@ public class StoreProductServiceImpl implements IStoreProductService { final UserSubscriptionsMapper userSubMapper; final OSSClientWrapper ossClient; final TencentAuthManager tencentAuthManager; + final FsNotice fsNotice; /** @@ -233,7 +233,6 @@ public class StoreProductServiceImpl implements IStoreProductService { return count; } - /** * 修改档口商品 * @@ -691,7 +690,7 @@ public class StoreProductServiceImpl implements IStoreProductService { /** * 模糊查询系统所有商品 * - * @param storeId 档口ID + * @param storeId 档口ID * @param prodArtNum 货号 * @return StoreProdFuzzyResDTO */ @@ -1098,19 +1097,17 @@ public class StoreProductServiceImpl implements IStoreProductService { * @param storeProd 档口产品 * @param storeProdDTO 档口产品新增入参 * @param storeName 档口名称 - * @throws IOException */ - private void createESDoc(StoreProduct storeProd, StoreProdDTO storeProdDTO, String storeName) throws IOException { + private void createESDoc(StoreProduct storeProd, StoreProdDTO storeProdDTO, String storeName) { ESProductDTO esProductDTO = this.getESDTO(storeProd, storeProdDTO, storeName); try { // 向索引中添加数据 CreateResponse createResponse = esClientWrapper.getEsClient().create(e -> e.index(Constants.ES_IDX_PRODUCT_INFO) .id(storeProd.getId().toString()).document(esProductDTO)); log.info("createResponse.result() = {}", createResponse.result()); - } catch (IOException | RuntimeException e) { - // 记录日志并抛出或处理异常 - log.error("向ES写入文档失败,商品ID: {}, 错误信息: {}", storeProd.getId(), e.getMessage(), e); - throw e; // 或者做其他补偿处理,比如异步重试 + } catch (Exception e) { + fsNotice.sendMsg2DefaultChat("新增商品,同步到ES 失败", "storeId:" + storeProd.getStoreId() + " prodArtNum: " + storeProd.getProdArtNum()); + throw new ServiceException("新增商品,同步到ES 失败,storeId:" + storeProd.getStoreId() + " prodArtNum: " + storeProd.getProdArtNum(), HttpStatus.ERROR); } } @@ -1120,17 +1117,16 @@ public class StoreProductServiceImpl implements IStoreProductService { * @param storeProd 档口商品 * @param updateDTO 档口商品更新入参 * @param storeName 档口名称 - * @throws IOException */ - private void updateESDoc(StoreProduct storeProd, StoreProdDTO updateDTO, String storeName) throws IOException { + private void updateESDoc(StoreProduct storeProd, StoreProdDTO updateDTO, String storeName) { ESProductDTO esProductDTO = this.getESDTO(storeProd, updateDTO, storeName); try { UpdateResponse updateResponse = esClientWrapper.getEsClient().update(u -> u .index(Constants.ES_IDX_PRODUCT_INFO).doc(esProductDTO).id(storeProd.getId().toString()), ESProductDTO.class); log.info("updateResponse.result() = {}", updateResponse.result()); - } catch (IOException | RuntimeException e) { - log.error("更新商品[{}]到ES失败: {}", storeProd.getId(), e.getMessage(), e); - throw e; // 或者根据业务需求进行重试、异步补偿等处理 + } catch (Exception e) { + fsNotice.sendMsg2DefaultChat("更新商品,同步到ES 失败", "storeProdId: " + storeProd.getId()); + throw new ServiceException("更新商品,同步到ES 失败,storeProdId:" + storeProd.getId(), HttpStatus.ERROR); } } @@ -1525,24 +1521,5 @@ public class StoreProductServiceImpl implements IStoreProductService { return cateAttrMap; } - /** - * 校验验证码 - * - * @param code 验证码 - * @param uuid 唯一标识 - * @return 结果 - */ - private void validateCaptcha(String code, String uuid) { - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; - String captcha = redisCache.getCacheObject(verifyKey); - redisCache.deleteObject(verifyKey); - if (captcha == null) { - throw new CaptchaExpireException(); - } - if (!StrUtil.emptyIfNull(code).equalsIgnoreCase(captcha)) { - throw new CaptchaException(); - } - } - }