가상투자 메뉴 기능 구현

This commit is contained in:
Macbook
2026-05-25 06:41:45 +09:00
parent 0cfe7fc84c
commit 8b373b11e3
33 changed files with 3897 additions and 99 deletions
+18 -4
View File
@@ -7,6 +7,7 @@ import SockJS from 'sockjs-client';
import { getStompSockJsUrl } from './backendApi';
type MessageHandler = (msg: IMessage) => void;
type ConnectionListener = (connected: boolean) => void;
interface TopicEntry {
handlers: Set<MessageHandler>;
@@ -16,8 +17,14 @@ interface TopicEntry {
let client: StompClient | null = null;
let connected = false;
const topics = new Map<string, TopicEntry>();
const connectionListeners = new Set<ConnectionListener>();
let disconnectTimer: ReturnType<typeof setTimeout> | null = null;
function notifyConnection(next: boolean): void {
connected = next;
connectionListeners.forEach(l => l(next));
}
function handlerCount(): number {
let n = 0;
for (const entry of topics.values()) n += entry.handlers.size;
@@ -51,12 +58,12 @@ function getOrCreateClient(): StompClient {
heartbeatIncoming: 10_000,
heartbeatOutgoing: 10_000,
onConnect: () => {
connected = true;
cancelPendingDisconnect();
notifyConnection(true);
resubscribeAll();
},
onDisconnect: () => {
connected = false;
notifyConnection(false);
for (const entry of topics.values()) {
entry.stompSub = undefined;
}
@@ -68,7 +75,7 @@ function getOrCreateClient(): StompClient {
console.warn('[stompChartBroker] WebSocket error', getStompSockJsUrl(), ev);
},
onWebSocketClose: () => {
connected = false;
notifyConnection(false);
for (const entry of topics.values()) {
entry.stompSub = undefined;
}
@@ -95,10 +102,17 @@ function scheduleDisconnect(): void {
return;
}
client.deactivate();
connected = false;
notifyConnection(false);
}, 5000);
}
/** STOMP 연결 상태 변경 구독 */
export function subscribeStompConnection(listener: ConnectionListener): () => void {
connectionListeners.add(listener);
listener(connected && Boolean(client?.connected));
return () => { connectionListeners.delete(listener); };
}
/**
* STOMP 토픽 구독 (참조 카운트). 반환 함수로 해제.
*/