Compare commits
2 Commits
4589592b67
...
e6df50bbb1
| Author | SHA1 | Date | |
|---|---|---|---|
| e6df50bbb1 | |||
| 57ad1fd67d |
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
import requests
|
import requests
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
@@ -51,40 +52,57 @@ def _run_generation(task_id: str, params: dict) -> None:
|
|||||||
|
|
||||||
update_task(task_id, "processing", 30, "음악 생성 중... (수 분 소요될 수 있습니다)")
|
update_task(task_id, "processing", 30, "음악 생성 중... (수 분 소요될 수 있습니다)")
|
||||||
|
|
||||||
|
# 1단계: 생성 요청 → ai_task_id 반환
|
||||||
resp = requests.post(
|
resp = requests.post(
|
||||||
f"{MUSIC_AI_SERVER_URL}/generate",
|
f"{MUSIC_AI_SERVER_URL}/generate",
|
||||||
json=params,
|
json=params,
|
||||||
timeout=600, # 10분
|
timeout=30,
|
||||||
stream=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
update_task(task_id, "failed", 0, "", error=f"AI 서버 오류: {resp.status_code} {resp.text[:200]}")
|
update_task(task_id, "failed", 0, "", error=f"AI 서버 오류: {resp.status_code} {resp.text[:200]}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
ai_task_id = resp.json().get("task_id")
|
||||||
|
if not ai_task_id:
|
||||||
|
update_task(task_id, "failed", 0, "", error="AI 서버 응답에 task_id가 없습니다")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 2단계: 상태 폴링 (최대 10분, 5초 간격) — AI 서버 progress/message 그대로 반영
|
||||||
|
remote_url = None
|
||||||
|
for _ in range(120):
|
||||||
|
time.sleep(5)
|
||||||
|
status_resp = requests.get(f"{MUSIC_AI_SERVER_URL}/status/{ai_task_id}", timeout=10)
|
||||||
|
status_data = status_resp.json()
|
||||||
|
ai_status = status_data.get("status")
|
||||||
|
|
||||||
|
# AI 서버의 progress/message를 로컬 task에 전달 (30~79 범위로 스케일)
|
||||||
|
ai_progress = status_data.get("progress", 0)
|
||||||
|
ai_message = status_data.get("message", "음악 생성 중...")
|
||||||
|
scaled = 30 + int(ai_progress * 0.49) # 30% ~ 79%
|
||||||
|
update_task(task_id, "processing", scaled, ai_message)
|
||||||
|
|
||||||
|
if ai_status == "succeeded":
|
||||||
|
remote_url = status_data.get("audio_url")
|
||||||
|
break
|
||||||
|
elif ai_status == "failed":
|
||||||
|
update_task(task_id, "failed", 0, "", error=status_data.get("error", "AI 서버 생성 실패"))
|
||||||
|
return
|
||||||
|
|
||||||
|
if not remote_url:
|
||||||
|
update_task(task_id, "failed", 0, "", error="AI 서버 타임아웃 (10분 초과)")
|
||||||
|
return
|
||||||
|
|
||||||
update_task(task_id, "processing", 80, "파일 저장 중...")
|
update_task(task_id, "processing", 80, "파일 저장 중...")
|
||||||
|
|
||||||
# AI 서버 응답: binary audio 또는 JSON {"audio_url": "..."}
|
|
||||||
content_type = resp.headers.get("content-type", "")
|
|
||||||
filename = f"{task_id}.mp3"
|
filename = f"{task_id}.mp3"
|
||||||
file_path = os.path.join(MUSIC_DATA_DIR, filename)
|
file_path = os.path.join(MUSIC_DATA_DIR, filename)
|
||||||
|
|
||||||
if "application/json" in content_type:
|
# 3단계: 오디오 파일 다운로드
|
||||||
result = resp.json()
|
dl = requests.get(remote_url, timeout=120, stream=True)
|
||||||
remote_url = result.get("audio_url") or result.get("url")
|
with open(file_path, "wb") as f:
|
||||||
if not remote_url:
|
for chunk in dl.iter_content(chunk_size=8192):
|
||||||
update_task(task_id, "failed", 0, "", error="AI 서버 응답에 audio_url이 없습니다")
|
f.write(chunk)
|
||||||
return
|
|
||||||
# 원격 URL에서 파일 다운로드
|
|
||||||
dl = requests.get(remote_url, timeout=120, stream=True)
|
|
||||||
with open(file_path, "wb") as f:
|
|
||||||
for chunk in dl.iter_content(chunk_size=8192):
|
|
||||||
f.write(chunk)
|
|
||||||
else:
|
|
||||||
# binary audio 직접 저장
|
|
||||||
with open(file_path, "wb") as f:
|
|
||||||
for chunk in resp.iter_content(chunk_size=8192):
|
|
||||||
f.write(chunk)
|
|
||||||
|
|
||||||
# audio_url은 항상 Nginx 상대경로 (Mixed Content 방지)
|
# audio_url은 항상 Nginx 상대경로 (Mixed Content 방지)
|
||||||
audio_url = f"/media/music/{filename}"
|
audio_url = f"/media/music/{filename}"
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ def init_db():
|
|||||||
quantity INTEGER NOT NULL,
|
quantity INTEGER NOT NULL,
|
||||||
avg_price REAL NOT NULL,
|
avg_price REAL NOT NULL,
|
||||||
sell_price REAL NOT NULL,
|
sell_price REAL NOT NULL,
|
||||||
|
commission REAL NOT NULL DEFAULT 0,
|
||||||
buy_amount REAL NOT NULL,
|
buy_amount REAL NOT NULL,
|
||||||
sell_amount REAL NOT NULL,
|
sell_amount REAL NOT NULL,
|
||||||
realized_profit REAL NOT NULL,
|
realized_profit REAL NOT NULL,
|
||||||
@@ -83,6 +84,11 @@ def init_db():
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
# sell_history 마이그레이션: commission 컬럼 추가
|
||||||
|
sh_cols = {r["name"] for r in conn.execute("PRAGMA table_info(sell_history)").fetchall()}
|
||||||
|
if "commission" not in sh_cols:
|
||||||
|
conn.execute("ALTER TABLE sell_history ADD COLUMN commission REAL NOT NULL DEFAULT 0")
|
||||||
|
|
||||||
def save_articles(articles: List[Dict[str, str]]) -> int:
|
def save_articles(articles: List[Dict[str, str]]) -> int:
|
||||||
count = 0
|
count = 0
|
||||||
with _conn() as conn:
|
with _conn() as conn:
|
||||||
@@ -212,13 +218,13 @@ def add_sell_history(data: Dict[str, Any]) -> Dict[str, Any]:
|
|||||||
cur = conn.execute("""
|
cur = conn.execute("""
|
||||||
INSERT INTO sell_history
|
INSERT INTO sell_history
|
||||||
(broker, ticker, name, quantity, avg_price, sell_price,
|
(broker, ticker, name, quantity, avg_price, sell_price,
|
||||||
buy_amount, sell_amount, realized_profit, realized_rate, sold_at)
|
commission, buy_amount, sell_amount, realized_profit, realized_rate, sold_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""", (
|
""", (
|
||||||
data["broker"], data["ticker"], data["name"], data["quantity"],
|
data["broker"], data["ticker"], data["name"], data["quantity"],
|
||||||
data["avg_price"], data["sell_price"], data["buy_amount"],
|
data["avg_price"], data["sell_price"], data.get("commission", 0),
|
||||||
data["sell_amount"], data["realized_profit"], data["realized_rate"],
|
data["buy_amount"], data["sell_amount"], data["realized_profit"],
|
||||||
data["sold_at"],
|
data["realized_rate"], data["sold_at"],
|
||||||
))
|
))
|
||||||
row = conn.execute("SELECT * FROM sell_history WHERE id = ?", (cur.lastrowid,)).fetchone()
|
row = conn.execute("SELECT * FROM sell_history WHERE id = ?", (cur.lastrowid,)).fetchone()
|
||||||
return dict(row)
|
return dict(row)
|
||||||
@@ -244,9 +250,9 @@ def get_sell_history(broker: str = None, days: int = None) -> List[Dict[str, Any
|
|||||||
|
|
||||||
def update_sell_history(record_id: int, data: Dict[str, Any]) -> Dict[str, Any] | None:
|
def update_sell_history(record_id: int, data: Dict[str, Any]) -> Dict[str, Any] | None:
|
||||||
fields = ["broker", "ticker", "name", "quantity", "avg_price", "sell_price",
|
fields = ["broker", "ticker", "name", "quantity", "avg_price", "sell_price",
|
||||||
"buy_amount", "sell_amount", "realized_profit", "realized_rate", "sold_at"]
|
"commission", "buy_amount", "sell_amount", "realized_profit", "realized_rate", "sold_at"]
|
||||||
set_clause = ", ".join(f"{f} = ?" for f in fields)
|
set_clause = ", ".join(f"{f} = ?" for f in fields)
|
||||||
values = [data[f] for f in fields] + [record_id]
|
values = [data.get(f, 0) if f == "commission" else data[f] for f in fields] + [record_id]
|
||||||
with _conn() as conn:
|
with _conn() as conn:
|
||||||
cur = conn.execute(f"UPDATE sell_history SET {set_clause} WHERE id = ?", values)
|
cur = conn.execute(f"UPDATE sell_history SET {set_clause} WHERE id = ?", values)
|
||||||
if cur.rowcount == 0:
|
if cur.rowcount == 0:
|
||||||
|
|||||||
Reference in New Issue
Block a user