feat: 搜索接口做redis缓存
This commit is contained in:
@@ -56,23 +56,90 @@ export class SearchService {
|
||||
@handleError('搜索执行失败')
|
||||
public async search(keyword: string): Promise<SearchResponse> {
|
||||
logger.info('开始执行搜索', { keyword });
|
||||
const token = await this.getToken();
|
||||
|
||||
const response = await axios.get<SearchResponse>(
|
||||
`${this.baseUrl}${config.searchService.endpoints.search}`,
|
||||
{
|
||||
params: { keyword },
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
// 1. 尝试从Redis获取缓存
|
||||
const cacheKey = `search:${keyword}`;
|
||||
const cachedResult = await this.redisService.get(cacheKey);
|
||||
if (cachedResult) {
|
||||
logger.info('从缓存中获取搜索结果', { keyword });
|
||||
return JSON.parse(cachedResult);
|
||||
}
|
||||
|
||||
// 2. 获取token并执行搜索
|
||||
let token = await this.getToken();
|
||||
let retryCount = 0;
|
||||
const maxRetries = 1;
|
||||
|
||||
while (retryCount <= maxRetries) {
|
||||
try {
|
||||
const response = await axios.get<SearchResponse>(
|
||||
`${this.baseUrl}${config.searchService.endpoints.search}`,
|
||||
{
|
||||
params: { keyword },
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// 3. 处理搜索结果
|
||||
if (response.data.success && response.data.data) {
|
||||
// 为每个结果项生成唯一ID并格式化数据
|
||||
const processedData = response.data.data.map(channelData => {
|
||||
const processedList = channelData.list.map(item => {
|
||||
const itemId = crypto.randomUUID();
|
||||
const processedItem = {
|
||||
itemId,
|
||||
driveType: item.cloudLinks?.[0]?.cloudType?.toLowerCase() || 'unknown',
|
||||
publishDate: new Date(item.pubDate).toISOString(),
|
||||
displayTitle: item.title,
|
||||
...item
|
||||
};
|
||||
|
||||
// 将单个结果项存入Redis,TTL设置为1天
|
||||
this.redisService.set(`item:${itemId}`, JSON.stringify(processedItem), { EX: 86400 })
|
||||
.catch(err => logger.error('缓存单个结果项失败', { error: err, itemId }));
|
||||
|
||||
return processedItem;
|
||||
});
|
||||
|
||||
return {
|
||||
...channelData,
|
||||
list: processedList
|
||||
};
|
||||
});
|
||||
|
||||
// 4. 将完整搜索结果存入Redis,TTL设置为5分钟
|
||||
const searchResult = {
|
||||
...response.data,
|
||||
data: processedData
|
||||
};
|
||||
await this.redisService.set(cacheKey, JSON.stringify(searchResult), { EX: 3600 });
|
||||
|
||||
logger.info('搜索完成', {
|
||||
keyword,
|
||||
resultCount: processedData.reduce((acc, channel) => acc + channel.list.length, 0)
|
||||
});
|
||||
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
throw new AppError('搜索结果格式错误', 500);
|
||||
} catch (error: any) {
|
||||
// 处理token失效的情况
|
||||
if (error.response?.status === 401 || error.response?.status === 403) {
|
||||
if (retryCount < maxRetries) {
|
||||
logger.warn('Token已失效,尝试重新获取', { retryCount });
|
||||
token = await this.getToken();
|
||||
retryCount++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
logger.info('搜索完成', {
|
||||
keyword,
|
||||
resultCount: response.data.data?.length || 0
|
||||
});
|
||||
return response.data;
|
||||
throw new AppError('搜索失败,请稍后重试', 500);
|
||||
}
|
||||
|
||||
@handleError('参数化搜索失败')
|
||||
|
||||
Reference in New Issue
Block a user