From 7fc6116a0ae7ed38049f6b7b93898ab178c3bc70 Mon Sep 17 00:00:00 2001 From: xxm Date: Fri, 28 Aug 2026 19:48:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20hk=5Frate=20DB=E4=BC=98=E5=85=88?= =?UTF-8?q?=E8=AF=BB=E5=86=99fx=5Frate=E8=A1=A8(=E7=9F=A5=E5=BE=AE?= =?UTF-8?q?=E6=96=B9=E6=A1=88,=E6=B6=88=E9=99=A4deploy=5Fguard=E6=8C=81?= =?UTF-8?q?=E7=BB=AD=E6=8A=A5=E8=AD=A6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hk_rate.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/hk_rate.py b/hk_rate.py index e880991e..de617128 100644 --- a/hk_rate.py +++ b/hk_rate.py @@ -18,6 +18,46 @@ from datetime import date CACHE_PATH = os.path.expanduser("~/.cache/hk_exchange_rate.json") CACHE_TTL = 86400 # 24小时,合理配置常量 +# 数据库路径 - 使用绝对路径 +DB_PATH = "/home/hmo/MoFin/data/mofin.db" + +def _get_rate_from_db(): + """从 fx_rate 表获取汇率""" + try: + import sqlite3 + conn = sqlite3.connect(DB_PATH) + conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训) + cursor = conn.execute( + "SELECT rate FROM fx_rate WHERE currency_pair='HKD_CNY' AND is_active=1 ORDER BY created_at DESC LIMIT 1" + ) + row = cursor.fetchone() + conn.close() + if row and 0.7 < row[0] < 1.0: + return round(float(row[0]), 6) + except Exception as e: + print(f"[hk_rate] 数据库读取失败: {e}", file=sys.stderr) + return None + +def _set_rate_in_db(rate, source='api_refresh'): + """将汇率写入 fx_rate 表""" + try: + import sqlite3 + conn = sqlite3.connect(DB_PATH) + conn.execute("PRAGMA busy_timeout=30000") # 2026-08-28 防并发写锁(DB损坏教训) + # 先将旧的设为 inactive + conn.execute("UPDATE fx_rate SET is_active=0 WHERE currency_pair='HKD_CNY'") + # 插入新汇率 + conn.execute( + "INSERT INTO fx_rate (currency_pair, rate, source, created_at, is_active) VALUES (?, ?, ?, datetime('now','localtime'), 1)", + ('HKD_CNY', rate, source) + ) + conn.commit() + conn.close() + return True + except Exception as e: + print(f"[hk_rate] 数据库写入失败: {e}", file=sys.stderr) + return False + # 不再硬编码备用值,每次取缓存中的最近一次有效汇率 def _load_last_rate(): """从缓存文件读取上次已知有效汇率""" @@ -70,12 +110,18 @@ def _fetch_rate(): def hkd_to_cny(force_refresh=False): - """获取 HKD→CNY 汇率,缓存过期则自动刷新""" + """获取 HKD→CNY 汇率,优先使用数据库中的权威汇率""" os.makedirs(os.path.dirname(CACHE_PATH), exist_ok=True) now = time.time() rate = None - # 读缓存 + # 1. 优先从数据库获取(权威源) + if not force_refresh: + rate = _get_rate_from_db() + if rate is not None: + return rate + + # 2. 读本地缓存 if not force_refresh: try: with open(CACHE_PATH) as f: @@ -87,11 +133,13 @@ def hkd_to_cny(force_refresh=False): if (cache_date == date.today().isoformat() and rate is not None and (now - cached_at) < CACHE_TTL): + # 写入数据库作为权威源 + _set_rate_in_db(rate, 'cache_sync') return rate except Exception: pass - # 刷新 + # 3. 刷新API rate = _fetch_rate() if rate is None: # API全挂,用缓存中的上次有效汇率 @@ -100,7 +148,7 @@ def hkd_to_cny(force_refresh=False): rate = 0.87 # 极限兜底,纯预防 print(f"[hk_rate] API不可达,使用 {rate} (fallback)", file=sys.stderr) else: - # 写缓存 + # 写本地缓存 try: with open(CACHE_PATH, "w") as f: json.dump({ @@ -111,6 +159,8 @@ def hkd_to_cny(force_refresh=False): }, f) except Exception: pass + # 写入数据库作为权威源 + _set_rate_in_db(rate, 'api_refresh') return rate @@ -121,4 +171,4 @@ def refresh_rate(): if __name__ == "__main__": r = hkd_to_cny() - print(f"HKD/CNY = {r}") + print(f"HKD/CNY = {r}") \ No newline at end of file