From 1c752e0f758bd8c61a9504d1a8b8382329de581f Mon Sep 17 00:00:00 2001 From: Nixevol Date: Thu, 6 Aug 2026 17:42:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=86=85=E7=BD=91API=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E7=BB=95=E8=BF=87=E7=B3=BB=E7=BB=9F=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aidocs/project_context.md | 6 +++++- main.py | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/aidocs/project_context.md b/aidocs/project_context.md index ab182ea..3bbbd18 100644 --- a/aidocs/project_context.md +++ b/aidocs/project_context.md @@ -86,4 +86,8 @@ - Each run follows only the group containing the globally newest source start time. It does not fall back or backfill older groups. Missing sources or no matching files produce `status=waiting` and a successful exit; storage API failures remain task failures. Multiple files from one source in a group select the latest source start time. - All workbook row start times must round into the target group. Result CSV and database rows use one normalized `metric_time` and the database result columns only; `hour_start` and `hour_end` were removed from summary CSV output. - Database time is checked before source ZIP and CellData downloads. A newer or equal database time skips source processing. Successful database output is archived through the Storage API under `干扰历史数据/YYYY-MM-DD/干扰数据处理结果_YYYYMMDDHHMMSS.csv`; an equal database time with a missing/empty history file is exported from the database and repaired. -- Eighteen tests pass on Windows and in the offline runtime image. Live read-only selection saw incomplete newest group `2026-08-06 15:00:00`, correctly waited for missing `5G下FDD干扰监控`, and did not produce output. Explicit read-only validation of complete group `2026-08-06 14:00:00` produced 1,092 rows with one normalized `metric_time` and the expected nine-column result schema. +- Nineteen tests pass on Windows and in the offline runtime image. Live read-only selection saw incomplete newest group `2026-08-06 15:00:00`, correctly waited for missing `5G下FDD干扰监控`, and did not produce output. Explicit read-only validation of complete group `2026-08-06 14:00:00` produced 1,092 rows with one normalized `metric_time` and the expected nine-column result schema. +- SSH deployment run `7a7c0bba3a0c41f5a5a9e83ad25ff2fd` processed the completed `2026-08-06 15:00:00` group successfully. It retained 1,082 high-interference rows, removed 853 lower-interference rows, matched coordinates for 1,074 rows, left 8 unmatched, and replaced 1,116 rows from the previous database time. +- Database verification found only `2026-08-06 15:00:00` and 1,082 rows. Of those, 887 have non-zero `nearby_count`, the maximum is 40, and all 8 rows without coordinates remain valid. The history CSV was uploaded with the expected nine columns and 1,082 rows to `干扰历史数据/2026-08-06/干扰数据处理结果_20260806150000.csv`. +- A second run `e1c81ada63234b3c85a377e1b46a1370` returned success with `status=skipped`, confirming that an existing database time plus a non-empty history file avoids duplicate work. +- `MetrixApiClient` uses a proxy-free opener because the API is an intranet service and the Windows system proxy previously converted direct requests into `502` responses. The verified Metrix API remains `http://188.5.127.115:18271`; external port `9082` currently serves CapacityReport and must not be used by this script. diff --git a/main.py b/main.py index 3db5d9f..c4c9134 100644 --- a/main.py +++ b/main.py @@ -19,7 +19,7 @@ import time from typing import Protocol from urllib.error import HTTPError, URLError from urllib.parse import quote, urlencode -from urllib.request import Request, urlopen +from urllib.request import ProxyHandler, Request, build_opener import warnings import zipfile @@ -225,6 +225,7 @@ class MetrixApiClient: raise ProcessingError("METRIX_API_TOKEN is required for Metrix API access") self.base_url = base_url.rstrip("/") self.token = token + self.opener = build_opener(ProxyHandler({})) def get_bytes(self, endpoint: str, query: dict[str, object] | None = None, timeout: int = 30) -> bytes: return self._request("GET", endpoint, query=query, timeout=timeout) @@ -285,7 +286,7 @@ class MetrixApiClient: last_error: Exception | None = None for attempt in range(3): try: - with urlopen(request, timeout=timeout) as response: + with self.opener.open(request, timeout=timeout) as response: return response.read() except HTTPError as exc: detail = exc.read().decode("utf-8", "replace")[:1000]