|
|
@@ -75,18 +75,27 @@ public class FeishuClientPool {
|
|
|
}
|
|
|
|
|
|
public Client getClient() {
|
|
|
- String indexStr = stringRedisTemplate.opsForList()
|
|
|
- .rightPopAndLeftPush(POOL_KEY, POOL_KEY);
|
|
|
- if (indexStr == null) {
|
|
|
- log.warn("账号池为空,尝试重新初始化");
|
|
|
- resetPoolIndexes(clients.size());
|
|
|
- indexStr = stringRedisTemplate.opsForList()
|
|
|
+ while (true) {
|
|
|
+ // 1. 从 Redis 循环队列取出索引(原子操作)
|
|
|
+ String indexStr = stringRedisTemplate.opsForList()
|
|
|
.rightPopAndLeftPush(POOL_KEY, POOL_KEY);
|
|
|
if (indexStr == null) {
|
|
|
- throw new CustomException("无法获取飞书账号索引,账号池不可用");
|
|
|
+ log.warn("账号池为空,尝试重新初始化");
|
|
|
+ resetPoolIndexes(clients.size());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int index = Integer.parseInt(indexStr);
|
|
|
+
|
|
|
+ // 2. 获取当前 clients 快照(volatile 读)
|
|
|
+ List<Client> currentClients = this.clients;
|
|
|
+
|
|
|
+ // 3. 如果索引越界(说明列表已被其他线程缩小),丢弃该索引并重试
|
|
|
+ if (index >= currentClients.size()) {
|
|
|
+ log.warn("索引 {} 已失效(当前账号数 {}),重试", index, currentClients.size());
|
|
|
+ continue;
|
|
|
}
|
|
|
+ return currentClients.get(index);
|
|
|
}
|
|
|
- return clients.get(Integer.parseInt(indexStr));
|
|
|
}
|
|
|
|
|
|
/**
|