알림목록 지표없음 문제 수정
This commit is contained in:
@@ -2,14 +2,20 @@
|
||||
* 매매 시그널 알림 목록 행 — 종목×전략 실시간 신호 스냅샷 (가상매매 카드 요약형과 동일 소스)
|
||||
*/
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { isStrategyMissingOnServer, loadStrategy, type StrategyDto } from '../utils/backendApi';
|
||||
import type { StrategyDto } from '../utils/backendApi';
|
||||
import { extractVirtualConditions } from '../utils/virtualStrategyConditions';
|
||||
import { normalizeConditionRow } from '../utils/virtualSignalMetrics';
|
||||
import {
|
||||
resolveNotificationStrategy,
|
||||
normalizeStrategyId,
|
||||
} from '../utils/resolveNotificationStrategy';
|
||||
import {
|
||||
fetchLiveSnapshot,
|
||||
type VirtualIndicatorSnapshot,
|
||||
} from './useVirtualIndicatorSnapshots';
|
||||
|
||||
const MAX_EMPTY_RETRIES = 10;
|
||||
|
||||
function staticFallback(
|
||||
market: string,
|
||||
strategyId: number,
|
||||
@@ -31,7 +37,9 @@ export function useTradeNotificationSignalSnapshot(
|
||||
market: string,
|
||||
strategyId: number | null | undefined,
|
||||
strategy: StrategyDto | undefined,
|
||||
strategyName: string | null | undefined,
|
||||
enabled: boolean,
|
||||
prefetchedStrategies?: StrategyDto[],
|
||||
pollMs = 3000,
|
||||
): { snapshot: VirtualIndicatorSnapshot | undefined; loading: boolean } {
|
||||
const [snapshot, setSnapshot] = useState<VirtualIndicatorSnapshot | undefined>();
|
||||
@@ -39,13 +47,15 @@ export function useTradeNotificationSignalSnapshot(
|
||||
const emptyRetryRef = useRef(0);
|
||||
const genRef = useRef(0);
|
||||
const refreshInFlightRef = useRef(false);
|
||||
/** strategy prop 이 undefined 일 때 직접 로드한 전략 캐시 */
|
||||
const fallbackStrategyRef = useRef<StrategyDto | null>(null);
|
||||
const resolvedStrategyRef = useRef<StrategyDto | undefined>();
|
||||
const effectiveStrategyIdRef = useRef<number | null>(null);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
if (!enabled || strategyId == null) {
|
||||
const rawId = normalizeStrategyId(strategyId);
|
||||
if (!enabled || rawId == null) {
|
||||
setSnapshot(undefined);
|
||||
setLoading(false);
|
||||
emptyRetryRef.current = 0;
|
||||
return;
|
||||
}
|
||||
if (refreshInFlightRef.current) return;
|
||||
@@ -55,28 +65,32 @@ export function useTradeNotificationSignalSnapshot(
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
let effectiveStrategy = strategy;
|
||||
if (!effectiveStrategy) {
|
||||
if (fallbackStrategyRef.current) {
|
||||
effectiveStrategy = fallbackStrategyRef.current;
|
||||
} else if (!isStrategyMissingOnServer(strategyId)) {
|
||||
try {
|
||||
const loaded = await loadStrategy(strategyId);
|
||||
if (loaded) {
|
||||
fallbackStrategyRef.current = loaded;
|
||||
effectiveStrategy = loaded;
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
if (gen !== genRef.current) return;
|
||||
let effectiveStrategy = strategy ?? resolvedStrategyRef.current;
|
||||
let effectiveId = effectiveStrategy?.id ?? effectiveStrategyIdRef.current ?? rawId;
|
||||
|
||||
if (!effectiveStrategy || effectiveStrategy.id !== rawId) {
|
||||
const resolved = await resolveNotificationStrategy(
|
||||
rawId,
|
||||
strategyName,
|
||||
prefetchedStrategies,
|
||||
);
|
||||
if (gen !== genRef.current) return;
|
||||
if (resolved.strategy) {
|
||||
effectiveStrategy = resolved.strategy;
|
||||
resolvedStrategyRef.current = resolved.strategy;
|
||||
}
|
||||
if (resolved.strategyId != null) {
|
||||
effectiveId = resolved.strategyId;
|
||||
effectiveStrategyIdRef.current = resolved.strategyId;
|
||||
}
|
||||
}
|
||||
|
||||
const pinFirst = emptyRetryRef.current === 0;
|
||||
let snap = await fetchLiveSnapshot(market, strategyId, effectiveStrategy, pinFirst);
|
||||
let snap = await fetchLiveSnapshot(market, effectiveId, effectiveStrategy, pinFirst);
|
||||
if (gen !== genRef.current) return;
|
||||
|
||||
if (!snap && effectiveStrategy) {
|
||||
snap = staticFallback(market, strategyId, effectiveStrategy) ?? null;
|
||||
snap = staticFallback(market, effectiveId, effectiveStrategy) ?? null;
|
||||
}
|
||||
|
||||
if (snap && snap.rows.length > 0) {
|
||||
@@ -87,24 +101,28 @@ export function useTradeNotificationSignalSnapshot(
|
||||
|
||||
if (gen === genRef.current) {
|
||||
setSnapshot(snap ?? undefined);
|
||||
const stillCollecting = (!snap || snap.rows.length === 0)
|
||||
&& emptyRetryRef.current < MAX_EMPTY_RETRIES;
|
||||
setLoading(stillCollecting);
|
||||
}
|
||||
} finally {
|
||||
refreshInFlightRef.current = false;
|
||||
if (gen === genRef.current) {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
}, [market, strategyId, strategy, enabled]);
|
||||
}, [market, strategyId, strategy, strategyName, enabled, prefetchedStrategies]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled || strategyId == null) {
|
||||
const rawId = normalizeStrategyId(strategyId);
|
||||
if (!enabled || rawId == null) {
|
||||
setSnapshot(undefined);
|
||||
setLoading(false);
|
||||
emptyRetryRef.current = 0;
|
||||
resolvedStrategyRef.current = undefined;
|
||||
effectiveStrategyIdRef.current = null;
|
||||
return;
|
||||
}
|
||||
emptyRetryRef.current = 0;
|
||||
fallbackStrategyRef.current = null;
|
||||
resolvedStrategyRef.current = strategy;
|
||||
effectiveStrategyIdRef.current = strategy?.id ?? rawId;
|
||||
setLoading(true);
|
||||
void refresh();
|
||||
const id = window.setInterval(() => void refresh(), pollMs);
|
||||
@@ -113,7 +131,7 @@ export function useTradeNotificationSignalSnapshot(
|
||||
genRef.current += 1;
|
||||
refreshInFlightRef.current = false;
|
||||
};
|
||||
}, [market, strategyId, enabled, pollMs, refresh]);
|
||||
}, [market, strategyId, strategyName, enabled, pollMs, refresh, strategy?.id]);
|
||||
|
||||
return { snapshot, loading };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user