차트 설정 수정
This commit is contained in:
@@ -90,6 +90,18 @@ async function requestOrThrow<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
return JSON.parse(text) as T;
|
||||
}
|
||||
|
||||
/** 서버에 없는 전략 ID — 삭제·만료 후 반복 404 방지 (태블릿·Safari 네트워크 로그 완화) */
|
||||
const strategyMissingIds = new Set<number>();
|
||||
|
||||
export function isStrategyMissingOnServer(strategyId: number): boolean {
|
||||
return strategyId > 0 && strategyMissingIds.has(strategyId);
|
||||
}
|
||||
|
||||
function markStrategyMissingFromPath(pathOnly: string): void {
|
||||
const m = pathOnly.match(/^\/strategies\/(\d+)(?:\/|$)/);
|
||||
if (m) strategyMissingIds.add(Number(m[1]));
|
||||
}
|
||||
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T | null> {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}${path}`, {
|
||||
@@ -100,8 +112,16 @@ async function request<T>(path: string, init?: RequestInit): Promise<T | null> {
|
||||
if (!res.ok) {
|
||||
const method = init?.method ?? 'GET';
|
||||
const guest403 = res.status === 403 && !hasRegisteredUser();
|
||||
const missing404 = res.status === 404 && method === 'GET';
|
||||
if (!guest403 && !missing404) {
|
||||
const pathOnly = path.split('?')[0];
|
||||
if (res.status === 404 && /^\/strategies\/\d+/.test(pathOnly)) {
|
||||
markStrategyMissingFromPath(pathOnly);
|
||||
}
|
||||
const quiet404 = res.status === 404 && (
|
||||
method === 'GET'
|
||||
|| pathOnly.includes('/repair-timeframes')
|
||||
|| /^\/strategies\/\d+/.test(pathOnly)
|
||||
);
|
||||
if (!guest403 && !quiet404) {
|
||||
console.error(`[backendApi] ${method} ${path} → ${res.status}`);
|
||||
}
|
||||
return null;
|
||||
@@ -1061,7 +1081,7 @@ export async function loadStrategies(): Promise<StrategyDto[]> {
|
||||
|
||||
/** 단일 전략 로드 */
|
||||
export async function loadStrategy(id: number): Promise<StrategyDto | null> {
|
||||
if (!hasRegisteredUser()) return null;
|
||||
if (!hasRegisteredUser() || id <= 0 || strategyMissingIds.has(id)) return null;
|
||||
return request<StrategyDto>(`/strategies/${id}`);
|
||||
}
|
||||
|
||||
@@ -1401,10 +1421,30 @@ export async function loadStrategyTimeframes(strategyId: number): Promise<string
|
||||
return list?.length ? list : ['1m'];
|
||||
}
|
||||
|
||||
/** DB DSL TIMEFRAME 래핑 보정 (3분봉 전략이 1m으로 평가되는 레거시 수정) */
|
||||
export async function repairStrategyTimeframes(strategyId: number): Promise<void> {
|
||||
if (!hasRegisteredUser()) return;
|
||||
await request(`/strategies/${strategyId}/repair-timeframes`, { method: 'POST' });
|
||||
const repairSkipIds = new Set<number>();
|
||||
const repairInflight = new Set<number>();
|
||||
|
||||
/** DB DSL TIMEFRAME 래핑 보정 — 전략 없으면 호출 안 함(404 방지) */
|
||||
export async function repairStrategyTimeframes(strategyId: number): Promise<boolean> {
|
||||
if (!hasRegisteredUser() || strategyId <= 0 || strategyMissingIds.has(strategyId)) return false;
|
||||
if (repairSkipIds.has(strategyId) || repairInflight.has(strategyId)) return false;
|
||||
|
||||
repairInflight.add(strategyId);
|
||||
try {
|
||||
const exists = await loadStrategy(strategyId);
|
||||
if (!exists) {
|
||||
repairSkipIds.add(strategyId);
|
||||
return false;
|
||||
}
|
||||
const ok = await request<StrategyDto>(
|
||||
`/strategies/${strategyId}/repair-timeframes`,
|
||||
{ method: 'POST' },
|
||||
);
|
||||
if (!ok) repairSkipIds.add(strategyId);
|
||||
return ok != null;
|
||||
} finally {
|
||||
repairInflight.delete(strategyId);
|
||||
}
|
||||
}
|
||||
|
||||
/** 차트 실시간 파이프라인 pin (STOMP warm-up) */
|
||||
|
||||
Reference in New Issue
Block a user