feat(网络请求): 增加超时和重试机制提升稳定性
为 asyncHttpsGet 添加超时参数,默认10秒 在 TuneHub 服务中实现3次重试机制,每次增加超时时间 优化错误日志记录,包含更多调试信息
This commit is contained in:
@@ -65,7 +65,7 @@ async function createJob(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let meta = {};
|
let meta = {};
|
||||||
const songId = request.urlJob && request.urlJob.meta.songId ? request.urlJob.meta.songId : "";
|
let songId = request.urlJob && request.urlJob.meta.songId ? request.urlJob.meta.songId : "";
|
||||||
logger.info(`[createJob] songId=${songId}`);
|
logger.info(`[createJob] songId=${songId}`);
|
||||||
|
|
||||||
// 先从 TuneHub 获取歌曲信息,避免显示原始 URL
|
// 先从 TuneHub 获取歌曲信息,避免显示原始 URL
|
||||||
|
|||||||
@@ -8,16 +8,21 @@ function buildApiUrl(params = {}) {
|
|||||||
return `${BaseUrl}?${searchParams.toString()}`;
|
return `${BaseUrl}?${searchParams.toString()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchJson(params = {}) {
|
async function fetchJson(params = {}, attempt = 1) {
|
||||||
const url = buildApiUrl(params);
|
const url = buildApiUrl(params);
|
||||||
const raw = await asyncHttpsGet(url);
|
// 重试时增加超时时间
|
||||||
|
const timeoutMs = Math.min(30000, 5000 + attempt * 5000);
|
||||||
|
logger.info(`[TuneHub] Fetching: ${url} (attempt ${attempt}, timeout ${timeoutMs}ms)`);
|
||||||
|
const raw = await asyncHttpsGet(url, timeoutMs);
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
|
logger.warn(`[TuneHub] No data received for ${url}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return JSON.parse(raw);
|
return JSON.parse(raw);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`TuneHub 返回非 JSON: ${url}`);
|
logger.error(`[TuneHub] Failed to parse JSON from ${url}: ${err.message}`);
|
||||||
|
logger.error(`[TuneHub] Raw response: ${raw.substring(0, 200)}...`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,15 +40,33 @@ async function getPlaylistDetail(source, playlistId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getSongInfo(source, songId) {
|
async function getSongInfo(source, songId) {
|
||||||
const response = await fetchJson({
|
// 增加重试机制,提高成功率
|
||||||
source,
|
const maxRetries = 3;
|
||||||
id: songId,
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||||
type: 'info',
|
try {
|
||||||
});
|
logger.info(`[TuneHub] Attempt ${attempt}/${maxRetries} to get song info: ${source}:${songId}`);
|
||||||
if (!response || response.code !== 200 || !response.data) {
|
const response = await fetchJson({
|
||||||
return false;
|
source,
|
||||||
|
id: songId,
|
||||||
|
type: 'info',
|
||||||
|
}, attempt);
|
||||||
|
if (response && response.code === 200 && response.data) {
|
||||||
|
logger.info(`[TuneHub] Success: ${source}:${songId}`);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
logger.warn(`[TuneHub] Failed attempt ${attempt}: code=${response?.code || 'no response'}, data=${!!response?.data}`);
|
||||||
|
if (attempt < maxRetries) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`[TuneHub] Error on attempt ${attempt}: ${error.message}`);
|
||||||
|
if (attempt < maxRetries) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return response.data;
|
logger.error(`[TuneHub] All ${maxRetries} attempts failed for ${source}:${songId}`);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchSongs(keyword, {
|
async function searchSongs(keyword, {
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
const https = require('https');
|
const https = require('https');
|
||||||
|
|
||||||
function asyncHttpsGet(url) {
|
function asyncHttpsGet(url, timeoutMs = 10000) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
console.error(`[asyncHttpsGet] Timeout after ${timeoutMs}ms: ${url}`);
|
||||||
|
resolve(null);
|
||||||
|
}, timeoutMs);
|
||||||
|
|
||||||
https.get(url, res => {
|
https.get(url, res => {
|
||||||
let data = '';
|
let data = '';
|
||||||
|
|
||||||
@@ -10,10 +15,12 @@ function asyncHttpsGet(url) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
res.on('end', () => {
|
res.on('end', () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
resolve(data.toString());
|
resolve(data.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
}).on('error', err => {
|
}).on('error', err => {
|
||||||
|
clearTimeout(timeout);
|
||||||
console.error(err);
|
console.error(err);
|
||||||
resolve(null);
|
resolve(null);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user