Add automatic database backup with download and restore docs.
Back up futures.db and uploads to /root/qihuo_backup on a daily schedule, expose backup downloads in settings, and document cross-server restore. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -51,6 +51,16 @@ from kline_stream import kline_hub, sse_format
|
||||
from kline_chart import generate_review_kline_chart, fetch_market_klines, MARKET_PERIODS
|
||||
from market import get_price as market_get_price, set_ths_refresh_token, get_quote_source_label
|
||||
from db_conn import connect_db
|
||||
from db_backup import (
|
||||
backup_dir,
|
||||
backup_in_progress,
|
||||
default_restore_dir,
|
||||
get_backup_last_at,
|
||||
list_backups,
|
||||
resolve_backup_file,
|
||||
schedule_backup,
|
||||
start_backup_worker,
|
||||
)
|
||||
from strategy.strategy_db import init_strategy_tables
|
||||
from install_trading import install_trading
|
||||
from vnpy_bridge import try_init_vnpy
|
||||
@@ -404,6 +414,12 @@ def init_db():
|
||||
set_setting("trailing_be_tick_buffer", "2")
|
||||
if not get_setting("pending_order_timeout_min"):
|
||||
set_setting("pending_order_timeout_min", "5")
|
||||
if not get_setting("backup_auto_enabled"):
|
||||
set_setting("backup_auto_enabled", "1")
|
||||
if not get_setting("backup_auto_hour"):
|
||||
set_setting("backup_auto_hour", "3")
|
||||
if not get_setting("backup_keep_count"):
|
||||
set_setting("backup_keep_count", "30")
|
||||
if not get_setting("fee_source_mode"):
|
||||
set_setting("fee_source_mode", "ctp")
|
||||
set_setting("fee_source_mode", "ctp")
|
||||
@@ -705,6 +721,7 @@ def start_background_threads():
|
||||
daemon=True,
|
||||
).start()
|
||||
threading.Thread(target=refresh_main_index, daemon=True).start()
|
||||
start_backup_worker(get_setting_fn=get_setting, set_setting_fn=set_setting)
|
||||
|
||||
|
||||
# —————————————— 登录 ——————————————
|
||||
@@ -1659,12 +1676,60 @@ def fees():
|
||||
)
|
||||
|
||||
|
||||
@app.route("/api/backup/list")
|
||||
@login_required
|
||||
def api_backup_list():
|
||||
return jsonify(
|
||||
{
|
||||
"dir": str(backup_dir()),
|
||||
"last_at": get_backup_last_at(get_setting),
|
||||
"running": backup_in_progress(),
|
||||
"items": list_backups(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.route("/api/backup/download/<filename>")
|
||||
@login_required
|
||||
def api_backup_download(filename):
|
||||
from flask import send_file
|
||||
|
||||
try:
|
||||
path = resolve_backup_file(filename)
|
||||
except (ValueError, FileNotFoundError) as exc:
|
||||
return jsonify({"error": str(exc)}), 404
|
||||
return send_file(path, as_attachment=True, download_name=path.name)
|
||||
|
||||
|
||||
@app.route("/settings", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def settings():
|
||||
if request.method == "POST":
|
||||
action = request.form.get("action")
|
||||
if action == "wechat":
|
||||
if action == "backup_now":
|
||||
ok, msg = schedule_backup(
|
||||
get_setting=get_setting,
|
||||
set_setting=set_setting,
|
||||
include_uploads=True,
|
||||
)
|
||||
flash(msg if ok else msg)
|
||||
elif action == "backup_config":
|
||||
auto = request.form.get("backup_auto_enabled") == "1"
|
||||
set_setting("backup_auto_enabled", "1" if auto else "0")
|
||||
try:
|
||||
hour = int(request.form.get("backup_auto_hour", "3") or 3)
|
||||
set_setting("backup_auto_hour", str(max(0, min(23, hour))))
|
||||
except ValueError:
|
||||
flash("自动备份小时无效")
|
||||
return redirect(url_for("settings"))
|
||||
try:
|
||||
keep = int(request.form.get("backup_keep_count", "30") or 30)
|
||||
set_setting("backup_keep_count", str(max(5, min(200, keep))))
|
||||
except ValueError:
|
||||
flash("保留份数无效")
|
||||
return redirect(url_for("settings"))
|
||||
flash("备份策略已保存")
|
||||
elif action == "wechat":
|
||||
webhook = request.form.get("wechat_webhook", "").strip()
|
||||
set_setting("wechat_webhook", webhook)
|
||||
flash("企业微信配置已保存")
|
||||
@@ -1813,6 +1878,14 @@ def settings():
|
||||
pending_order_timeout_min=get_setting("pending_order_timeout_min", "5"),
|
||||
nav_items=get_nav_items(get_setting),
|
||||
nav_toggles=NAV_TOGGLES,
|
||||
backup_dir=str(backup_dir()),
|
||||
backup_last_at=get_backup_last_at(get_setting),
|
||||
backup_running=backup_in_progress(),
|
||||
backup_items=list_backups(),
|
||||
backup_auto_enabled=get_setting("backup_auto_enabled", "1") == "1",
|
||||
backup_auto_hour=get_setting("backup_auto_hour", "3"),
|
||||
backup_keep_count=get_setting("backup_keep_count", "30"),
|
||||
backup_restore_dir=default_restore_dir(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user