From 289204780a1218e795bb1c1fd5519ec6342fe0b9 Mon Sep 17 00:00:00 2001 From: swpa Date: Tue, 19 May 2026 18:25:10 +0800 Subject: [PATCH] feat: Finalize JSON cache architecture and prepare for PostgreSQL migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 穩定並完善現有基於 JSON 檔案的 running/full 雙軌快取機制 - 確認 __metadata__ (版本與掃描時間) 的讀寫邏輯運作正常 - 確立下一階段 PostgreSQL + asyncpg 的升級藍圖與 Schema 設計 - 準備建立 feature/postgres-migration 分支進行資料庫無痛轉移 --- cmts_scraper.py | 41 +++-- filters_full.json | 3 + filters_running.json | 3 + index.html | 48 ++++-- routers/config.py | 119 ++++++++------ routers/leaf_options.py | 131 ++++++++++------ routers/lock.py | 85 +++++----- static/api.js | 69 ++++---- static/app.js | 340 ++++++++++++++++++++++++++++++++-------- static/edit-mode.js | 254 +++++++++++++++++------------- static/my_icon.png | Bin 0 -> 622 bytes static/tree-ui.js | 98 +++++++++--- 12 files changed, 798 insertions(+), 393 deletions(-) create mode 100644 filters_full.json create mode 100644 filters_running.json create mode 100644 static/my_icon.png diff --git a/cmts_scraper.py b/cmts_scraper.py index 7acd79f..fed0efb 100644 --- a/cmts_scraper.py +++ b/cmts_scraper.py @@ -142,7 +142,8 @@ def parse_device_response(output: str) -> dict: return {"type": "unknown", "options": [], "current_value": None, "raw_output": output.strip()} -async def sync_cmts_leaves_async(host, username, password, leaf_paths: list): +# 🌟 1. 函數簽名加上 config_type 參數,預設為 "running" +async def sync_cmts_leaves_async(host, username, password, leaf_paths: list, config_type: str = "running"): try: total_paths = len(leaf_paths) processed_count = 0 @@ -188,6 +189,9 @@ async def sync_cmts_leaves_async(host, username, password, leaf_paths: list): await read_until_quiet(timeout=1.5) for path in batch: + # 🌟 優化 1:強迫讓出事件迴圈控制權,讓 FastAPI 去處理其他使用者的請求 + await asyncio.sleep(0.01) + # --- 步驟 1:發送 '?' 查詢 --- command_to_send = f"{path} ?" process.stdin.write(command_to_send) @@ -254,13 +258,22 @@ async def sync_cmts_leaves_async(host, username, password, leaf_paths: list): finally: if conn: conn.close() - # --- 步驟 3:寫入快取檔 --- + # --- 步驟 3:寫入快取檔 --- try: - cache_file = "cmts_leaf_options_cache.json" - cache_data = {} - if os.path.exists(cache_file): - with open(cache_file, "r", encoding="utf-8") as f: - cache_data = json.load(f) + # 🌟 2. 動態決定快取檔名 (加入 IP 隔離) + safe_host = host.replace(".", "_") + cache_file = f"{safe_host}_{config_type}_cache.json" + + # ========================================== + # 🌟 優化 2-A:將「讀取」舊快取檔丟到背景執行緒 + # ========================================== + def read_json_from_file(filepath): + if os.path.exists(filepath): + with open(filepath, "r", encoding="utf-8") as f: + return json.load(f) + return {} + + cache_data = await asyncio.to_thread(read_json_from_file, cache_file) # 🌟 新增:寫入 Metadata (版本與掃描時間) if "__metadata__" not in cache_data: @@ -277,9 +290,16 @@ async def sync_cmts_leaves_async(host, username, password, leaf_paths: list): result_data[p]["updated_at"] = current_ts cache_data[p] = result_data[p] - with open(cache_file, "w", encoding="utf-8") as f: - json.dump(cache_data, f, indent=4, ensure_ascii=False) - print(f"💾 [Debug] 第 {batch_idx + 1}/{len(batches)} 批次已提早寫入快取檔!(版本: {cmts_version})") + # ========================================== + # 🌟 優化 2-B:將「寫入」新快取檔丟到背景執行緒 + # ========================================== + def write_json_to_file(filepath, data): + with open(filepath, "w", encoding="utf-8") as f: + json.dump(data, f, indent=4, ensure_ascii=False) + + await asyncio.to_thread(write_json_to_file, cache_file, cache_data) + + print(f"💾 [Debug] 第 {batch_idx + 1}/{len(batches)} 批次已非同步寫入快取檔!(版本: {cmts_version}, 檔案: {cache_file})") except Exception as e: print(f"⚠️ 提早寫入快取失敗: {e}") @@ -290,3 +310,4 @@ async def sync_cmts_leaves_async(host, username, password, leaf_paths: list): except Exception as e: yield json.dumps({"event": "error", "message": f"爬蟲嚴重錯誤: {str(e)}"}) + "\n" + diff --git a/filters_full.json b/filters_full.json new file mode 100644 index 0000000..ba3788a --- /dev/null +++ b/filters_full.json @@ -0,0 +1,3 @@ +{ + "hidden_keys": [] +} \ No newline at end of file diff --git a/filters_running.json b/filters_running.json new file mode 100644 index 0000000..ba3788a --- /dev/null +++ b/filters_running.json @@ -0,0 +1,3 @@ +{ + "hidden_keys": [] +} \ No newline at end of file diff --git a/index.html b/index.html index 7bb0506..f20b803 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,7 @@ Harmonic CMTS Manager + @@ -42,8 +43,8 @@
@@ -161,8 +162,10 @@
@@ -247,10 +250,13 @@
- -