chore: baseline — ORM migration + systemd deploy + MCP server + daily check

- ORM migration: models/ops 重构
- deploy: 标准化 systemd timer/service 部署体系
- MCP server: 5 个只读工具(任务/状态/数据集)
- daily check: 数据一致性巡检
- watch: task_watch 后台监控
- kline_daily: 麦蕊优先,时间门禁15:00
- 删除: task_industry_sector, task_sector_features
This commit is contained in:
gao
2026-07-21 16:37:00 +08:00
parent 91e83a3b0b
commit 8f016f25df
94 changed files with 4117 additions and 1176 deletions
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
# 部署 market-sync systemd units 到 /etc/systemd/system/
# 2026-07-09 新增: market-sync-worker.service(长驻进程, 调度 schedule_* 任务)
#
# 用法: sudo bash bin/deploy_systemd.sh
#
# 跑这个脚本会:
# 1. 复制 bin/systemd/market-sync*.{service,timer} 到 /etc/systemd/system/
# 2. systemctl daemon-reload
# 3. enable + start market-sync-worker.service
# 4. 不动已存在的 .timer (它们都已 enable, 重复 enable 无副作用)
set -euo pipefail
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
SYSTEMD_SRC="$REPO_DIR/bin/systemd"
SYSTEMD_DST="/etc/systemd/system"
if [ "$(id -u)" -ne 0 ]; then
echo "❌ 必须用 sudo 跑: sudo bash $0" >&2
exit 1
fi
echo "=== 1. 复制 unit files ==="
for f in "$SYSTEMD_SRC"/market-sync*.{service,timer}; do
[ -f "$f" ] || continue
name="$(basename "$f")"
cp -v "$f" "$SYSTEMD_DST/$name"
chmod 644 "$SYSTEMD_DST/$name"
done
echo ""
echo "=== 2. daemon-reload ==="
systemctl daemon-reload
echo ""
echo "=== 3. 启用 + 启动 worker 长驻进程(关键!) ==="
if ! systemctl is-enabled --quiet market-sync-worker.service; then
systemctl enable market-sync-worker.service
fi
# 如果已通过 nohup 启动了, 先 kill 掉避免双跑
if pgrep -f "app\.entrypoints\.worker" >/dev/null; then
echo " ⚠️ 检测到手动启动的 worker 进程, 先 kill"
pkill -TERM -f "app\.entrypoints\.worker" || true
sleep 2
pkill -KILL -f "app\.entrypoints\.worker" 2>/dev/null || true
fi
systemctl restart market-sync-worker.service
sleep 2
systemctl status market-sync-worker.service --no-pager | head -10
echo ""
echo "=== 4. 列出所有 market-sync timer (验证) ==="
systemctl list-timers market-sync* --no-pager 2>&1 | head -20
echo ""
echo "✅ 部署完成"
echo " - 长驻 worker: systemctl status market-sync-worker.service"
echo " - 看任务执行: tail -f logs/worker_manual_*.log (本进程) 或 journalctl -u market-sync-worker -f (systemd 接管后)"
echo " - 巡检: .venv/bin/python bin/daily_sync_check.py"
+185
View File
@@ -0,0 +1,185 @@
#!/bin/bash
# market_sync systemd 一键部署脚本
#
# 用途:把 bin/systemd/*.service 和 *.timer 同步到 /etc/systemd/system/
# 解决 work #04 检测到的 5 处 drift。
#
# 运行:sudo bash bin/systemd_deploy.sh
#
# 设计原则:
# - 必须 sudo(写 /etc/systemd/system/ + daemon-reload
# - 幂等:重复运行无副作用
# - 显示 plan → 等待确认 → 执行
# - 失败立即中止,不留半套状态
set -e
PROJECT_ROOT="/home/gao/Development/quant_home/market_sync"
REPO_UNITS_DIR="$PROJECT_ROOT/bin/systemd"
ETC_UNITS_DIR="/etc/systemd/system"
# ── 0. 前置检查 ─────────────────────────────────────────────────────────────
if [ "$(id -u)" -ne 0 ]; then
echo "❌ 必须 sudo 运行:sudo bash $0"
exit 1
fi
if [ ! -d "$REPO_UNITS_DIR" ]; then
echo "❌ repo unit 目录不存在: $REPO_UNITS_DIR"
exit 1
fi
# ── 1. 计算 plan ────────────────────────────────────────────────────────────
declare -a TO_COPY=() # repo→etc 拷贝
declare -a TO_REMOVE=() # etc 中孤儿(repo 已删)
declare -a TO_RESTART_SVC=() # service 文件变了需要 daemon-reload + restart
# repo 中所有 market-sync* unit
mapfile -t REPO_UNITS < <(find "$REPO_UNITS_DIR" -maxdepth 1 -type f \( -name "*.service" -o -name "*.timer" \) -printf '%f\n' | sort)
# /etc 中所有 market-sync* unit
mapfile -t ETC_UNITS < <(find "$ETC_UNITS_DIR" -maxdepth 1 -type f \( -name "market-sync*.service" -o -name "market-sync*.timer" \) -printf '%f\n' | sort 2>/dev/null || true)
# drift 1: repo 有 /etc 没装
for u in "${REPO_UNITS[@]}"; do
if [ ! -f "$ETC_UNITS_DIR/$u" ]; then
TO_COPY+=("$u")
fi
done
# drift 2: 两边都有但内容不一致
for u in "${REPO_UNITS[@]}"; do
if [ -f "$ETC_UNITS_DIR/$u" ]; then
if ! diff -q "$REPO_UNITS_DIR/$u" "$ETC_UNITS_DIR/$u" > /dev/null 2>&1; then
TO_COPY+=("$u")
if [[ "$u" == *.service ]]; then
TO_RESTART_SVC+=("${u%.service}")
fi
fi
fi
done
# drift 3: /etc 有 repo 没维护(孤儿)
for u in "${ETC_UNITS[@]}"; do
found=0
for r in "${REPO_UNITS[@]}"; do
if [ "$r" = "$u" ]; then found=1; break; fi
done
if [ $found -eq 0 ]; then
TO_REMOVE+=("$u")
fi
done
# ── 2. 显示 plan ────────────────────────────────────────────────────────────
echo "============================================================"
echo "market_sync systemd deploy plan"
echo "============================================================"
echo
echo "Repo units: ${#REPO_UNITS[@]}"
echo "/etc units: ${#ETC_UNITS[@]}"
echo
if [ ${#TO_COPY[@]} -eq 0 ] && [ ${#TO_REMOVE[@]} -eq 0 ]; then
echo "✅ 无 drift 需要修复。无需执行。"
exit 0
fi
if [ ${#TO_COPY[@]} -gt 0 ]; then
echo "📋 将要拷贝 ($(echo "${TO_COPY[@]}" | tr ' ' '\n' | wc -l) 个):"
for u in "${TO_COPY[@]}"; do
echo " cp bin/systemd/$u → /etc/systemd/system/$u"
done
echo
fi
if [ ${#TO_RESTART_SVC[@]} -gt 0 ]; then
echo "🔄 将要重启 service ($(echo "${TO_RESTART_SVC[@]}" | tr ' ' '\n' | wc -l) 个):"
for s in "${TO_RESTART_SVC[@]}"; do
echo " systemctl reset-failed $s.service"
done
echo
fi
if [ ${#TO_REMOVE[@]} -gt 0 ]; then
echo "🗑️ 将要删除 etc 中的孤儿 ($(echo "${TO_REMOVE[@]}" | tr ' ' '\n' | wc -l) 个):"
for u in "${TO_REMOVE[@]}"; do
echo " rm /etc/systemd/system/$u"
done
echo
fi
# ── 3. 等待确认 ────────────────────────────────────────────────────────────
read -p "确认执行?[y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "已取消。"
exit 0
fi
# ── 4. 执行 ─────────────────────────────────────────────────────────────────
echo
echo "=== 执行 ==="
# 4a. cp 漂移的 unit
for u in "${TO_COPY[@]}"; do
cp -v "$REPO_UNITS_DIR/$u" "$ETC_UNITS_DIR/$u"
done
# 4b. 删孤儿
for u in "${TO_REMOVE[@]}"; do
rm -v "$ETC_UNITS_DIR/$u"
done
# 4c. reload systemd
echo
echo "=== systemctl daemon-reload ==="
systemctl daemon-reload
# 4d. reset-failed + restart 修改过的 service
for s in "${TO_RESTART_SVC[@]}"; do
if systemctl is-enabled "${s}.service" 2>/dev/null | grep -q enabled; then
systemctl reset-failed "${s}.service" || true
echo " reset-failed ${s}.service (没自动 restart — 由 timer 自然触发)"
fi
done
# 4e. 启用新 timer(如果有)
for u in "${TO_COPY[@]}"; do
if [[ "$u" == *.timer ]]; then
timer="${u%.timer}"
if systemctl list-unit-files "${timer}.timer" 2>/dev/null | grep -q "${timer}.timer"; then
if ! systemctl is-enabled "${timer}.timer" 2>/dev/null | grep -q enabled; then
systemctl enable "${timer}.timer"
echo " enable ${timer}.timer"
fi
fi
fi
done
# ── 5. 验证 ────────────────────────────────────────────────────────────────
echo
echo "=== 验证 ==="
echo "Repo units: ${#REPO_UNITS[@]}"
echo "/etc units: $(find "$ETC_UNITS_DIR" -maxdepth 1 -type f -name 'market-sync*.service' -o -name 'market-sync*.timer' | wc -l)"
drift_count=0
for u in "${REPO_UNITS[@]}"; do
if [ -f "$ETC_UNITS_DIR/$u" ]; then
if ! diff -q "$REPO_UNITS_DIR/$u" "$ETC_UNITS_DIR/$u" > /dev/null 2>&1; then
echo "$u 仍有 drift"
drift_count=$((drift_count + 1))
fi
else
echo "$u 仍未部署"
drift_count=$((drift_count + 1))
fi
done
echo
if [ $drift_count -eq 0 ]; then
echo "✅ 所有 unit 已对齐,0 drift"
echo
echo "下一步:跑 .venv/bin/python bin/daily_sync_check.py --report-only 验证"
else
echo "❌ 还有 $drift_count 处 drift,请检查"
exit 1
fi