import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 新建服务类处理晚到旅客逻辑
*/
@Slf4j
@Component
public class LatePassengerCheckService {
@Resource
private IPaxTripClient paxTripClient;
@Resource
private IFlightInfoClient flightServiceClient;
@Resource
private IDataFimsFlightDynamicClient dataFimsFlightDynamicClient;
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 定时任务每5分钟检查一次 本身数据传输的时候 就已经标记晚到旅客 redis也存值了,这里可以用于其他模块无法标记的 测试使用
@Scheduled(cron = "0 */5 * * * ?")
public void checkLatePassengers() {
// 1. 查询所有 已经值机 的旅客
R<List<PaxTripEntity>> todayTripR = paxTripClient.getTodayTrip();
if (!todayTripR.isSuccess()) {
log.error("查询今天行程失败");
}
List<PaxTripEntity> checkedInPassengers = todayTripR.getData();
for (PaxTripEntity passenger : checkedInPassengers) {
// 有晚值机 标识才继续执行
if (!passenger.getLateCheckIn()) {
continue;
}
// 检查是否已经完成外呼
if (Boolean.TRUE.equals(passenger.getLateCallCompleted())) {
continue;
}
// 将需要外呼的旅客存入Redis(使用Hash结构存储详细信息)
redisTemplate.opsForHash().put(CallInfo.REDIS_KEY,
passenger.getId().toString(), // 使用旅客行程ID作为hash key
new CallInfo(passenger, 0) // 值包含旅客信息和重试次数
);
// 设置过期时间防止数据堆积(24小时)
redisTemplate.expire(CallInfo.REDIS_KEY, 24, TimeUnit.HOURS);
}
}
// 新增独立的外呼处理任务(每1分钟执行一次)
@Scheduled(cron = "0 */1 * * * ?")
public void handleRedisCallQueue() {
// 获取所有待处理旅客ID
Set<Object> passengerIds = redisTemplate.opsForHash().keys(CallInfo.REDIS_KEY);
// 如果没有需要 提醒的 旅客信息 直接返回
for (Object idObj : passengerIds) {
String passengerId = (String) idObj;
CallInfo callInfo = (CallInfo) redisTemplate.opsForHash().get(CallInfo.REDIS_KEY, passengerId);
try {
// 执行外呼操作
boolean callResult = triggerCall(callInfo.getPassenger().getPaxPhone());
if (callResult) {
// 外呼成功后标记为已完成
PaxTripEntity byId = paxTripClient.getById(callInfo.getPassenger().getId());
byId.setLateCallCompleted(true);
paxTripClient.update(byId);
// 从Redis删除记录
redisTemplate.opsForHash().delete(CallInfo.REDIS_KEY, passengerId);
} else {
// 失败时增加重试次数
callInfo.incrementRetryCount();
if (callInfo.getRetryCount() >= CallInfo.MAX_RETRY) {
log.warn("旅客{}外呼已达最大重试次数", passengerId);
redisTemplate.opsForHash().delete(CallInfo.REDIS_KEY, passengerId);
} else {
// 更新重试次数
redisTemplate.opsForHash().put(CallInfo.REDIS_KEY, passengerId, callInfo);
}
}
} catch (Exception e) {
log.error("外呼处理异常: {}", e.getMessage());
}
}
}
// TODO: 实现外呼接口调用
// 修改外呼方法返回调用结果
private boolean triggerCall(String phoneNumber) {
try {
// 模拟外呼成功/失败
log.info("正在呼叫: {}", phoneNumber);
return true; // 实际应根据接口返回判断
} catch (Exception e) {
log.error("外呼失败: {}", e.getMessage());
return false;
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
// 新增内部类记录外呼信息
@Data
@AllArgsConstructor
public class CallInfo {
// 新增Redis相关配置
public static final String REDIS_KEY = "late_passenger:call_queue";
public static final int MAX_RETRY = 3; // 最大重试次数
private PaxTripEntity passenger;
private Integer retryCount;
public void incrementRetryCount() {
this.retryCount++;
}
}
LatePassengerCheckService 是一个用于处理晚到旅客逻辑的Spring服务类。它通过定时任务每5分钟检查一次已值机的旅客,筛选出有晚值机标识且未完成外呼的旅客,并将其信息存入Redis,设置24小时过期时间。此外,每1分钟执行一次独立的外呼处理任务,从Redis中获取待处理旅客信息,执行外呼操作。外呼成功后,标记旅客为已完成并从Redis中删除记录;若外呼失败,则增加重试次数,达到最大重试次数后删除记录。该服务通过Redis管理外呼队列,确保晚到旅客得到及时处理。