반복적인 IPC 오류 해결, 봇 오류 해결, 인증 오류 해결, 서버 자원 할당 오류 해결, 코드 리팩토링

This commit is contained in:
2026-02-14 18:03:13 +09:00
parent 4fd0aa91bc
commit 9dbf6e6791
15 changed files with 1452 additions and 847 deletions

View File

@@ -1,11 +1,7 @@
import os
import uvicorn
import subprocess
import sys
import multiprocessing
from fastapi import FastAPI, Request
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime
from contextlib import asynccontextmanager
from modules.config import Config
@@ -13,100 +9,121 @@ from modules.services.ollama import OllamaManager
from modules.services.kis import KISClient
from modules.services.news import NewsCollector
from modules.services.telegram import TelegramMessenger
from modules.bot import AutoTradingBot
from modules.utils.process_tracker import ProcessTracker, ProcessWatchdog
from modules.services.telegram_bot.runner import run_telegram_bot_standalone
# 전역 객체
bot_process = None
telegram_process = None
messenger = TelegramMessenger()
ai_agent = None
kis_client = None
news_collector = None
watchdog = None
import multiprocessing
from modules.bot import AutoTradingBot
from modules.utils.process_tracker import ProcessTracker
from modules.services.telegram_bot.runner import run_telegram_bot_standalone
# 봇 실행 래퍼 함수
def run_trading_bot():
def run_trading_bot(ipc_lock, command_queue, shutdown_event):
"""트레이딩 봇 실행 래퍼"""
ProcessTracker.register("Trading Bot Main")
bot = AutoTradingBot()
bot = AutoTradingBot(ipc_lock=ipc_lock, command_queue=command_queue,
shutdown_event=shutdown_event)
bot.loop()
@asynccontextmanager
async def lifespan(app: FastAPI):
# [Startup]
global bot_process, telegram_process, messenger, ai_agent, kis_client, news_collector
global ai_agent, kis_client, news_collector, watchdog
# 1. 설정 검증
Config.validate()
# 2. 전역 객체 초기화 (서버용)
# [Process Tracker] 초기화
# 2. 좀비 프로세스 정리
try:
ProcessTracker.check_and_kill_zombies()
ProcessTracker.clear()
ProcessTracker.register("Main Server (Uvicorn Worker)")
except: pass
except Exception:
pass
# 3. 전역 객체 초기화
ai_agent = OllamaManager()
kis_client = KISClient()
news_collector = NewsCollector()
print("🤖 Starting AI Trading Bot & Telegram Bot (Multimedia Mode)...")
# 3. 멀티프로세스 실행
# (1) 트레이딩 봇
bot_process = multiprocessing.Process(target=run_trading_bot)
bot_process.start()
# (2) 텔레그램 봇 (Polling)
telegram_process = multiprocessing.Process(target=run_telegram_bot_standalone)
telegram_process.start()
# [Process Tracker] 자식 프로세스 PID 기록 (부모 관점)
try:
with open(ProcessTracker.FILE_PATH, "a", encoding="utf-8") as f:
f.write(f"{bot_process.pid}: Trading Bot Process (Parent View)\n")
f.write(f"{telegram_process.pid}: Telegram Bot Process (Parent View)\n")
except: pass
messenger.send_message("🖥️ **[Server Started]** Windows AI Server (Refactored) Online.")
yield
# [Shutdown]
print("🛑 Shutting down processes...")
if telegram_process and telegram_process.is_alive():
print(" - Stopping Telegram Bot...")
telegram_process.join(timeout=5)
if telegram_process.is_alive():
telegram_process.terminate()
telegram_process.join()
# 4. 공유 리소스 생성
ipc_lock = multiprocessing.Lock()
command_queue = multiprocessing.Queue()
shutdown_event = multiprocessing.Event()
print("[Server] Starting AI Trading Bot & Telegram Bot...")
# 5. 자식 프로세스 생성
bot_args = (ipc_lock, command_queue, shutdown_event)
telegram_args = (ipc_lock, command_queue, shutdown_event)
bot_process = multiprocessing.Process(
target=run_trading_bot, args=bot_args)
bot_process.start()
telegram_process = multiprocessing.Process(
target=run_telegram_bot_standalone, args=telegram_args)
telegram_process.start()
# 6. Watchdog 시작
watchdog = ProcessWatchdog(shutdown_event=shutdown_event)
watchdog.watch("Trading Bot", bot_process, run_trading_bot, bot_args)
watchdog.watch("Telegram Bot", telegram_process,
run_telegram_bot_standalone, telegram_args)
watchdog.start()
messenger.send_message("[Server Started] Windows AI Server Online.")
yield
# [Shutdown]
print("[Server] Shutting down...")
shutdown_event.set()
if watchdog:
watchdog.stop()
# 자식 프로세스 종료
for name in ["Trading Bot", "Telegram Bot"]:
proc = watchdog.get_process(name) if watchdog else None
if proc and proc.is_alive():
print(f" - Stopping {name}...")
proc.join(timeout=5)
if proc.is_alive():
proc.terminate()
proc.join(timeout=3)
# SharedMemory 정리
try:
from multiprocessing.shared_memory import SharedMemory
shm = SharedMemory(name=Config.SHM_NAME, create=False)
shm.close()
shm.unlink()
except Exception:
pass
messenger.send_message("[Server Stopped] Server Shutting Down.")
if bot_process and bot_process.is_alive():
print(" - Stopping Trading Bot...")
bot_process.join(timeout=5)
if bot_process.is_alive():
bot_process.terminate()
bot_process.join()
messenger.send_message("🛑 **[Server Stopped]** Server Shutting Down.")
app = FastAPI(title="Windows AI Stock Server", lifespan=lifespan)
@app.middleware("http")
async def log_requests(request: Request, call_next):
print(f"📥 {request.method} {request.url}")
print(f"[HTTP] {request.method} {request.url}")
response = await call_next(request)
return response
# 모델 정의
class ManualOrderRequest(BaseModel):
ticker: str
action: str # BUY, SELL
action: str
quantity: int
@app.get("/")
def index():
vram = 0
@@ -118,6 +135,7 @@ def index():
"service": "Windows AI Server (Refactored)"
}
@app.get("/trade/balance")
@app.get("/api/trade/balance")
async def get_balance():
@@ -125,28 +143,29 @@ async def get_balance():
return {"error": "Server not initialized"}
return kis_client.get_balance()
@app.post("/trade/order")
@app.post("/api/trade/order")
async def manual_order(req: ManualOrderRequest):
ticker = req.ticker
qty = req.quantity
action = req.action.upper()
result = "No Action"
if action == "BUY":
result = kis_client.buy_stock(ticker, qty)
elif action == "SELL":
result = kis_client.sell_stock(ticker, qty)
return {"status": "executed", "kis_result": result}
@app.post("/analyze/portfolio")
@app.post("/api/analyze/portfolio")
async def analyze_portfolio():
# 간단화된 분석 로직
balance = kis_client.get_balance()
news = news_collector.get_market_news()
prompt = f"""
Analyze this portfolio with recent news:
Portfolio: {balance}
@@ -156,13 +175,13 @@ async def analyze_portfolio():
analysis = ai_agent.request_inference(prompt)
return {"analysis": analysis}
if __name__ == "__main__":
# [안정성] 서버 시작 시 이전 좀비 프로세스 정리
# 서버 시작 시 좀비 프로세스 정리
try:
from modules.utils.process_tracker import ProcessTracker
ProcessTracker.check_and_kill_zombies()
except: pass
# Reload=True는 멀티프로세싱 자식 프로세스 관리에 취약하므로 비활성화 권장
print("🚀 Starting Windows AI Server...")
except Exception:
pass
print("[Server] Starting Windows AI Server...")
uvicorn.run("main_server:app", host="0.0.0.0", port=8000, reload=False)