fix: 修复连接池泄漏(conn.close改为put_db) + put_db处理已关闭连接 + 添加日线同步cron

This commit is contained in:
freedakgmail
2026-07-22 07:12:09 +08:00
parent 488ef6b8e2
commit 9a5e24ccd6
5 changed files with 54 additions and 54 deletions
+15 -15
View File
@@ -2,7 +2,7 @@
管理后台 API 路由
"""
from flask import Blueprint, request, jsonify, session, render_template
from db import get_db
from db import get_db, put_db
from psycopg2.extras import RealDictCursor
from werkzeug.security import generate_password_hash
import functools
@@ -182,7 +182,7 @@ def admin_required(f):
if not row or not row[0]:
return jsonify({'success': False, 'error': '无管理员权限'}), 403
finally:
conn.close()
put_db(conn)
return f(*args, **kwargs)
return decorated
@@ -201,7 +201,7 @@ def admin_page():
if not row or not row[0]:
return '无权访问', 403
finally:
conn.close()
put_db(conn)
return render_template('admin.html')
@@ -281,7 +281,7 @@ def dashboard():
return jsonify({'success': True, 'data': stats})
finally:
conn.close()
put_db(conn)
# ========== 用户管理 ==========
@@ -339,7 +339,7 @@ def list_users():
return jsonify({'success': True, 'data': users})
finally:
conn.close()
put_db(conn)
@bp.route('/api/admin/users/<int:user_id>', methods=['GET'])
@@ -437,7 +437,7 @@ def get_user_detail(user_id):
}
})
finally:
conn.close()
put_db(conn)
@bp.route('/api/admin/users/<int:user_id>/reset_password', methods=['POST'])
@@ -461,7 +461,7 @@ def reset_user_password(user_id):
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/api/admin/users/<int:user_id>/toggle_admin', methods=['POST'])
@@ -483,7 +483,7 @@ def toggle_admin(user_id):
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/api/admin/users/<int:user_id>', methods=['DELETE'])
@@ -509,7 +509,7 @@ def delete_user(user_id):
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
# ========== 用户数据管理 ==========
@@ -526,7 +526,7 @@ def delete_user_watchlist(user_id, code):
conn.commit()
return jsonify({'success': True})
finally:
conn.close()
put_db(conn)
@bp.route('/api/admin/users/<int:user_id>/trades/<int:trade_id>', methods=['DELETE'])
@@ -541,7 +541,7 @@ def delete_user_trade(user_id, trade_id):
conn.commit()
return jsonify({'success': True})
finally:
conn.close()
put_db(conn)
# ========== 系统数据 ==========
@@ -568,7 +568,7 @@ def scan_history():
""")
return jsonify({'success': True, 'data': [dict(r) for r in cur.fetchall()]})
finally:
conn.close()
put_db(conn)
@bp.route('/api/admin/data_stats', methods=['GET'])
@@ -603,7 +603,7 @@ def data_stats():
return jsonify({'success': True, 'data': {'tables': result, 'logs': logs}})
finally:
conn.close()
put_db(conn)
# ========== 全景扫描管理 ==========
@@ -786,7 +786,7 @@ def kline_sync_status():
total_stocks = cur.fetchone()[0]
cur.close()
conn.close()
put_db(conn)
is_running = _is_kline_sync_running()
@@ -1308,7 +1308,7 @@ def admin_scan_status():
triggered = cur.fetchone()[0]
cur.close()
conn.close()
put_db(conn)
is_running = _is_scan_running()
+11 -11
View File
@@ -313,7 +313,7 @@ def ai_analyze_stream(stock_code):
from flask import Response
from services.doubao_api import analyze_stock_stream, format_fund_flow, format_market_cap
from services.mairui_api import get_realtime_price as mairui_price, get_financial_indicators
from db import get_db
from db import get_db, put_db
def generate():
# 获取股票数据
@@ -384,7 +384,7 @@ def ai_analyze_stream(stock_code):
stock_data['triggered_count'] = scan_row['triggered_count'] or 0
cur2.close()
conn.close()
put_db(conn)
except Exception as e:
print(f"获取数据失败: {e}")
@@ -399,7 +399,7 @@ def ai_analyze_stream(stock_code):
_cur.execute("INSERT INTO ai_call_log (user_id, stock_code, stock_name) VALUES (%s, %s, %s)",
(_uid, stock_code, stock_name))
_conn.commit()
_conn.close()
_put_db(conn)
except Exception:
pass
@@ -421,7 +421,7 @@ def ai_analyze(stock_code):
try:
from services.doubao_api import analyze_stock
from services.mairui_api import get_realtime_price as mairui_price, get_financial_indicators
from db import get_db
from db import get_db, put_db
# 获取股票数据
stock_data = {}
@@ -467,7 +467,7 @@ def ai_analyze(stock_code):
'super_pct': float(row[3]) if row[3] else 0,
})
stock_data['fund_flow_3days'] = fund_flow
conn.close()
put_db(conn)
except Exception as e:
print(f"获取资金流向失败: {e}")
@@ -603,7 +603,7 @@ def batch_technical_signals():
scan_map[row['code']] = row
cur.close()
conn.close()
put_db(conn)
except Exception as e:
print(f"批量扫描获取数据失败: {e}")
@@ -925,7 +925,7 @@ def get_scan_results():
recommend_counts[disp] = recommend_counts.get(disp, 0) + 1
cur.close()
conn.close()
put_db(conn)
return jsonify({
'success': True,
@@ -1003,7 +1003,7 @@ def signal_alerts():
WHERE code IN ({placeholders})
""", stock_codes)
price_rows = cur.fetchall()
conn.close()
put_db(conn)
price_map = {}
change_map = {}
@@ -1153,7 +1153,7 @@ def get_scan_status():
triggered = cur.fetchone()[0]
cur.close()
conn.close()
put_db(conn)
return jsonify({
'success': True,
@@ -1241,7 +1241,7 @@ def get_scan_strategy():
""", (scan_date,))
rows = cur.fetchall()
cur.close()
conn.close()
put_db(conn)
tier1, tier2, tier3, tier4 = [], [], [], []
for r in rows:
@@ -1376,7 +1376,7 @@ def get_bull_stocks():
for p in cur.fetchall():
price_map[p['code']] = {'price': float(p['price']), 'change_pct': float(p.get('change_pct') or 0)}
conn.close()
put_db(conn)
# ---- 批量计算综合评分 ----
scores_map = None
+8 -8
View File
@@ -6,7 +6,7 @@ import pandas as pd
from datetime import datetime, timedelta
from services.stock_service import get_stock_fund_flow, load_cached_data
from services.stock_algorithms import get_kline_data as algo_get_kline_data
from db import get_db
from db import get_db, put_db
bp = Blueprint('market', __name__, url_prefix='/api')
@@ -40,7 +40,7 @@ def db_realtime_price(stock_code):
'data': dict(row)
})
finally:
conn.close()
put_db(conn)
@bp.route('/db/realtime_prices', methods=['POST'])
@@ -71,7 +71,7 @@ def db_realtime_prices():
'data': [dict(row) for row in rows]
})
finally:
conn.close()
put_db(conn)
@bp.route('/db/fund_flow_today/<stock_code>', methods=['GET'])
@@ -102,7 +102,7 @@ def db_fund_flow_today(stock_code):
'data': dict(row)
})
finally:
conn.close()
put_db(conn)
@bp.route('/db/fund_flow_today_batch', methods=['POST'])
@@ -135,7 +135,7 @@ def db_fund_flow_today_batch():
'data': [dict(row) for row in rows]
})
finally:
conn.close()
put_db(conn)
@bp.route('/db/data_status', methods=['GET'])
@@ -171,7 +171,7 @@ def db_data_status():
'recent_logs': [dict(log) for log in logs]
})
finally:
conn.close()
put_db(conn)
# ============ 原有API(兼容) ============
@@ -305,7 +305,7 @@ def get_fund_flow_rank():
return jsonify({'success': True, 'data': flow_data, 'total': len(flow_data),
'source': 'cache'})
finally:
_conn.close()
_put_db(conn)
return jsonify({'success': True, 'data': [], 'total': 0})
except Exception as e:
@@ -389,7 +389,7 @@ def get_fundamental(stock_code):
'triggered_count': sig_row[2] or 0,
}
conn.close()
put_db(conn)
except Exception as e:
print(f"获取数据失败: {e}")
+12 -12
View File
@@ -29,7 +29,7 @@ def init_user_config(user_id):
cur.execute("SELECT * FROM sim_config WHERE user_id = %s", (user_id,))
return cur.fetchone()
finally:
conn.close()
put_db(conn)
@bp.route('/config', methods=['GET'])
@@ -82,7 +82,7 @@ def update_config():
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/trades', methods=['GET'])
@@ -114,7 +114,7 @@ def get_trades():
trades = cur.fetchall()
return jsonify({'success': True, 'trades': trades})
finally:
conn.close()
put_db(conn)
@bp.route('/positions', methods=['GET'])
@@ -140,7 +140,7 @@ def get_positions():
positions = cur.fetchall()
return jsonify({'success': True, 'positions': positions})
finally:
conn.close()
put_db(conn)
@bp.route('/stats', methods=['GET'])
@@ -261,7 +261,7 @@ def get_stats():
'history': list(reversed(history)) if history else []
})
finally:
conn.close()
put_db(conn)
@bp.route('/execute', methods=['POST'])
@@ -381,7 +381,7 @@ def execute_trade():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/auto_execute', methods=['POST'])
@@ -532,7 +532,7 @@ def auto_execute():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/update_prices', methods=['POST'])
@@ -588,7 +588,7 @@ def update_prices():
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/reset', methods=['POST'])
@@ -612,7 +612,7 @@ def reset_simulation():
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/trigger_trade', methods=['POST'])
@@ -628,7 +628,7 @@ def trigger_trade():
conn = get_db()
if conn:
result = execute_smart_trade(conn, user_id, scan_date=None)
conn.close()
put_db(conn)
if result.get('success'):
results = result.get('results', [])
buy_count = len([r for r in results if r['type'] == 'buy'])
@@ -651,7 +651,7 @@ def trigger_trade():
cur.execute("SELECT trade_quantity FROM sim_config WHERE user_id = %s", (user_id,))
config = cur.fetchone()
trade_quantity = config['trade_quantity'] if config else 1000
conn.close()
put_db(conn)
else:
trade_quantity = 1000
@@ -730,4 +730,4 @@ def get_today_trades():
}
})
finally:
conn.close()
put_db(conn)
+8 -8
View File
@@ -43,7 +43,7 @@ def get_algo_templates():
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
# ═══════════════════════════════════════════════════════
@@ -78,7 +78,7 @@ def get_algo_config():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/config', methods=['POST'])
@@ -111,7 +111,7 @@ def save_algo_config():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
@bp.route('/apply_template', methods=['POST'])
@@ -139,7 +139,7 @@ def apply_template():
conn.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
# ═══════════════════════════════════════════════════════
@@ -164,7 +164,7 @@ def get_status():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
# ═══════════════════════════════════════════════════════
@@ -205,7 +205,7 @@ def trigger_smart_trade():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
# ═══════════════════════════════════════════════════════
@@ -242,7 +242,7 @@ def get_signals():
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)
# ═══════════════════════════════════════════════════════
@@ -284,4 +284,4 @@ def get_position_meta():
traceback.print_exc()
return jsonify({'success': False, 'error': str(e)}), 500
finally:
conn.close()
put_db(conn)