perf(search): 유튜브뮤직 검색과 ytsearch 폴백을 병렬 실행 (실험 브랜치)
측정으로 확인한 낭비: YoutubeMusic.getSearchUrl 적중률이 6/10(평균 548ms)이라, 빗나가는 40% 에서는 YTM 을 끝까지 기다린 뒤 다시 ytsearch(~0.5초)를 도는 순차 대기가 통째로 버려지고 있었다. 변경: resolveQuery 기본 경로에서 ytsearch 폴백 검색을 먼저 띄워두고 YTM 결과를 기다린다. - YTM 적중 -> 폴백 결과는 버리고 기존과 동일하게 동작(Lavalink 검색 1회가 헛돌 뿐) - YTM 빗나감 -> 이미 진행 중인 폴백 결과를 그대로 사용(추가 대기 0) - 버려지는 폴백 promise 는 catch 를 달아 unhandledRejection 방지 - " Topic" 중복 부가 방지 조건 추가 실측 A/B(YTM 이 빗나가는 3곡, 검색+해석+리졸브 구간): 기존 1500 / 1688 / 1391ms -> 신규 1224 / 1180 / 1399ms 재생은 3곡 모두 성공, 관찰 중 멈춤 0. 남은 병목: 음성접속 핸드셰이크(0.5~1.3초)는 디스코드 왕복이라 단축 여지가 거의 없다.
This commit is contained in:
@@ -121,10 +121,22 @@ export class LavalinkManager {
|
||||
// 기본: 유튜브뮤직(YoutubeMusic.getSearchUrl) 우선 → 결과가 없거나 애매(커버/방송/무관)하면
|
||||
// getSearchUrl이 null을 주고, 공식 오디오를 잘 잡는 `ytsearch:... Topic`로 폴백한다.
|
||||
// ('-p' 플래그를 붙이면 스포티파이 우선 검색)
|
||||
// 기본 경로는 YTM 검색과 ytsearch 폴백을 '동시에' 출발시킨다.
|
||||
// YTM 적중률이 약 60%라, 빗나가는 40%에서는 YTM(~0.5초)을 기다린 뒤 다시 ytsearch(~0.5초)를
|
||||
// 도는 순차 대기가 통째로 낭비된다. 미리 같이 돌려두면 빗나가도 추가 대기가 없다.
|
||||
// (적중 시에는 폴백 결과를 버리므로 Lavalink 검색 1회가 헛돌지만 비용이 작다.)
|
||||
let searchText: string;
|
||||
let pendingFallback: ReturnType<typeof node.rest.resolve> | null = null;
|
||||
if (isUrl) searchText = text;
|
||||
else if (flags.has('p')) searchText = (await Spotify.getSearchUrl(text)) ?? (await YoutubeMusic.getSearchUrl(text)) ?? `ytsearch:${text}`;
|
||||
else searchText = (await YoutubeMusic.getSearchUrl(text)) ?? `ytsearch:${text}`;
|
||||
else {
|
||||
const fallbackText = `ytsearch:${text}` + (flags.has('o') ? "" : " Topic");
|
||||
pendingFallback = node.rest.resolve(fallbackText);
|
||||
pendingFallback.catch(() => {}); // 적중해서 버려질 때 unhandledRejection 방지
|
||||
const ytm = await YoutubeMusic.getSearchUrl(text).catch(() => null);
|
||||
searchText = ytm ?? fallbackText;
|
||||
if (ytm) pendingFallback = null; // YTM 적중 → 폴백 결과는 사용하지 않음
|
||||
}
|
||||
// 스포티파이 트랙 URL은 Lavalink가 유튜브 '영상(뮤비)'으로 폴백한다(유튜브뮤직 연결돼 있어도).
|
||||
// 대시보드에서 고른 스포티파이 곡이나 `-p` 결과가 트랙 URL이면, 메타데이터(제목+아티스트)로
|
||||
// 유튜브뮤직 '오디오'를 직접 찾아 대체한다(텍스트 검색 경로와 동일하게 원곡 오디오 우선).
|
||||
@@ -136,8 +148,9 @@ export class LavalinkManager {
|
||||
searchText = (await YoutubeMusic.getSearchUrl(q)) ?? `ytsearch:${q}`;
|
||||
}
|
||||
}
|
||||
if (searchText.startsWith("ytsearch") && !flags.has('o')) searchText += " Topic";
|
||||
const result = await node.rest.resolve(searchText);
|
||||
if (searchText.startsWith("ytsearch") && !flags.has('o') && !searchText.endsWith(" Topic")) searchText += " Topic";
|
||||
// 위에서 미리 띄워둔 폴백 검색이 있으면 그 결과를 그대로 쓴다(중복 요청 방지).
|
||||
const result = pendingFallback ? await pendingFallback : await node.rest.resolve(searchText);
|
||||
if (!result || result.loadType === LoadType.EMPTY || result.loadType === LoadType.ERROR) {
|
||||
if (result?.loadType === LoadType.ERROR) Logger.error(`[LavalinkManager] loadtype ERROR: ${result.data.message}`);
|
||||
return null;
|
||||
|
||||
@@ -13,9 +13,9 @@ services:
|
||||
- SELFTEST_GUILD_ID=1352269198297923648
|
||||
- SELFTEST_VOICE_CHANNEL_ID=1352269198914621465
|
||||
- SELFTEST_TEXT_CHANNEL_ID=1421342055774289980
|
||||
- SELFTEST_QUERY=https://www.youtube.com/watch?v=E7EOjkGVmyo
|
||||
- SELFTEST_WATCH_SEC=1920
|
||||
- SELFTEST_QUERY=aespa Supernova
|
||||
- SELFTEST_WATCH_SEC=15
|
||||
- YTRESOLVER_ENABLED=true
|
||||
- YTRESOLVER_URL=http://192.168.10.5:8780
|
||||
- YTRESOLVER_URL=http://192.168.10.5:8779
|
||||
volumes:
|
||||
- ./testdb:/db
|
||||
|
||||
Reference in New Issue
Block a user