package com.zsElectric.boot.charging.quartz; import com.fasterxml.jackson.core.JsonProcessingException; import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo; import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper; import com.zsElectric.boot.charging.service.ChargingBusinessService; import com.zsElectric.boot.charging.vo.ChargingPricePolicyVO; import com.zsElectric.boot.charging.vo.QueryStationsInfoVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; /** * 充电站信息同步定时任务 * * @author system * @since 2025-12-11 */ @Slf4j @Component @RequiredArgsConstructor public class ChargingJob { private final ChargingBusinessService chargingBusinessService; private final ThirdPartyConnectorInfoMapper connectorInfoMapper; // 任务执行标记,防止并发执行 private volatile boolean isPricePolicySyncRunning = false; private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); /** * 同步充电站信息 * 每5分钟执行一次,从第三方接口获取充电站信息并存储到数据库 */ // @Scheduled(cron = "0 0/15 * * * ?") public void syncStationsInfo() { log.info("开始执行充电站信息同步定时任务"); try { // 获取当前时间作为查询时间 String lastQueryTime = LocalDateTime.now().minusMinutes(30).format(FORMATTER); // 分页查询,每次查询100条 Integer pageNo = 1; Integer pageSize = 100; log.info("查询参数 - LastQueryTime: {}, PageNo: {}, PageSize: {}", lastQueryTime, pageNo, pageSize); // 调用业务服务查询充电站信息(会自动保存到数据库) QueryStationsInfoVO result = chargingBusinessService.queryStationsInfo(lastQueryTime, pageNo, pageSize); if (result != null && result.getStationInfos() != null) { log.info("充电站信息同步完成,共同步 {} 个充电站", result.getStationInfos().size()); } else { log.warn("充电站信息同步结果为空"); } } catch (JsonProcessingException e) { log.error("充电站信息同步失败 - JSON处理异常", e); } catch (Exception e) { log.error("充电站信息同步失败 - 系统异常", e); } log.info("充电站信息同步定时任务执行结束"); } /** * 定时同步设备价格策略信息 * 每10分钟执行一次,查询所有充电桩的价格策略并存储到数据库 * cron表达式: 0 10 * * * ? 表示每10分钟执行 */ // @Scheduled(cron = "0 */10 * * * ?") public void syncEquipmentPricePolicy() { // 检查任务是否正在执行,防止并发 if (isPricePolicySyncRunning) { log.warn("价格策略同步任务正在执行中,跳过本次调度"); return; } isPricePolicySyncRunning = true; log.info("开始执行设备价格策略同步定时任务"); try { // 查询所有充电桩接口信息 List connectorList = connectorInfoMapper.selectList(null); if (CollectionUtils.isEmpty(connectorList)) { log.warn("未查询到充电桩接口信息,跳过价格策略同步"); return; } log.info("开始同步价格策略,总共 {} 个充电桩接口", connectorList.size()); int successCount = 0; int failCount = 0; // 遍历每个充电桩接口,查询价格策略 for (ThirdPartyConnectorInfo connector : connectorList) { try { String connectorId = connector.getConnectorId(); String equipmentId = connector.getEquipmentId(); log.info("查询价格策略 - connectorId: {}, equipmentId: {}", connectorId, equipmentId); // 调用业务服务查询价格策略(会自动保存到数据库) ChargingPricePolicyVO result = chargingBusinessService.queryEquipBusinessPolicy(equipmentId, connectorId); // 立即休眠10秒,避免触发第三方接口保护机制 // 第三方接口可能有频率限制,需要足够的间隔时间 // Thread.sleep(18000); // 10秒间隔 if (result != null && result.getSuccStat() != null && result.getSuccStat() == 0) { successCount++; log.info("价格策略同步成功 - connectorId: {}, 时段数: {}", connectorId, result.getSumPeriod()); } else { failCount++; log.warn("价格策略同步失败 - connectorId: {}, 失败原因: {}, 跳过该接口继续处理下一个", connectorId, result != null ? result.getFailReason() : "返回结果为空"); continue; // 跳过失败的接口,继续处理下一个 } // } catch (InterruptedException e) { // Thread.currentThread().interrupt(); // log.error("线程休眠被中断 - connectorId: {}", connector.getConnectorId(), e); // failCount++; // break; // 中断后退出循环 } catch (Exception e) { failCount++; log.error("同步价格策略失败 - connectorId: {}", connector.getConnectorId(), e); } } log.info("设备价格策略同步完成 - 成功: {}, 失败: {}, 总数: {}", successCount, failCount, connectorList.size()); } catch (Exception e) { log.error("设备价格策略同步定时任务执行异常", e); } finally { // 确保任务执行完毕后释放锁 isPricePolicySyncRunning = false; log.info("设备价格策略同步定时任务执行结束"); } } }