Files
auto-stock/backend/app/realtime/event_handler.py

129 lines
4.3 KiB
Python

"""
Event Handler
실시간 시세 이벤트 핸들러 관리
"""
from enum import Enum
from typing import Dict, List, Callable, Any, Awaitable
import logging
import asyncio
logger = logging.getLogger(__name__)
class EventType(Enum):
"""이벤트 타입"""
PRICE_UPDATE = "PRICE_UPDATE" # 현재가 업데이트
ORDERBOOK_UPDATE = "ORDERBOOK_UPDATE" # 호가 업데이트
EXECUTION = "EXECUTION" # 체결 발생
ORDER_CONFIRM = "ORDER_CONFIRM" # 주문 체결 확인
ERROR = "ERROR" # 에러 발생
CONNECTED = "CONNECTED" # 연결 성공
DISCONNECTED = "DISCONNECTED" # 연결 해제
class EventHandler:
"""
실시간 이벤트 핸들러 관리자
이벤트 타입별로 핸들러 함수를 등록하고 실행
"""
def __init__(self):
self.handlers: Dict[EventType, List[Callable]] = {
event_type: [] for event_type in EventType
}
self.global_handlers: List[Callable] = [] # 모든 이벤트 수신
logger.info("📡 EventHandler 초기화")
def register(
self,
event_type: EventType,
handler: Callable[[Dict[str, Any]], Awaitable[None]]
):
"""
이벤트 핸들러 등록
Args:
event_type: 이벤트 타입
handler: 비동기 핸들러 함수 (event_data를 받아 처리)
"""
if handler not in self.handlers[event_type]:
self.handlers[event_type].append(handler)
logger.info(f"✅ 핸들러 등록: {event_type.value} -> {handler.__name__}")
def unregister(self, event_type: EventType, handler: Callable):
"""핸들러 등록 해제"""
if handler in self.handlers[event_type]:
self.handlers[event_type].remove(handler)
logger.info(f"❌ 핸들러 해제: {event_type.value} -> {handler.__name__}")
def register_global(self, handler: Callable[[EventType, Dict[str, Any]], Awaitable[None]]):
"""모든 이벤트를 수신하는 글로벌 핸들러 등록"""
if handler not in self.global_handlers:
self.global_handlers.append(handler)
logger.info(f"🌍 글로벌 핸들러 등록: {handler.__name__}")
async def emit(
self,
event_type: EventType,
event_data: Dict[str, Any]
):
"""
이벤트 발생 및 핸들러 실행
Args:
event_type: 이벤트 타입
event_data: 이벤트 데이터
"""
logger.debug(f"📤 이벤트 발생: {event_type.value}")
# 타입별 핸들러 실행
handlers = self.handlers.get(event_type, [])
tasks = []
for handler in handlers:
try:
task = asyncio.create_task(handler(event_data))
tasks.append(task)
except Exception as e:
logger.error(f"❌ 핸들러 실행 오류 [{handler.__name__}]: {e}", exc_info=True)
# 글로벌 핸들러 실행
for global_handler in self.global_handlers:
try:
task = asyncio.create_task(global_handler(event_type, event_data))
tasks.append(task)
except Exception as e:
logger.error(f"❌ 글로벌 핸들러 오류: {e}", exc_info=True)
# 모든 핸들러 완료 대기 (non-blocking)
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
def clear(self, event_type: Optional[EventType] = None):
"""핸들러 초기화"""
if event_type:
self.handlers[event_type].clear()
logger.info(f"🧹 핸들러 초기화: {event_type.value}")
else:
for handlers in self.handlers.values():
handlers.clear()
self.global_handlers.clear()
logger.info("🧹 전체 핸들러 초기화")
def get_stats(self) -> Dict[str, Any]:
"""핸들러 통계"""
return {
"handlers": {
event_type.value: len(handlers)
for event_type, handlers in self.handlers.items()
},
"global_handlers": len(self.global_handlers)
}
# 싱글톤
event_handler = EventHandler()