问题:app.py:auto_monitor_job(定时)和 routes/api.py:run_monitor(手动) 各自维护了一份几乎相同但细节不一致的写入逻辑,同一条数据经不同入口落库后 latest_time / source / offset / file_count 可能不同。 - 新增 services/time_utils.py:calculate_offset 下沉到无依赖模块,避免 db_ingest 与 routes.api 互相 import 形成循环。routes/api.py 里 re-export 一次,保证 app.py 原有的 from routes.api import calculate_offset 不失效。 - 新增 services/db_ingest.py:ingest_device_data(),承载全部入库细节,只 add/flush 不 commit,事务边界交给调用方。 - routes/api.py:run_monitor 瘦身为「触发爬虫 -> 调管道 -> 提交」。 - models.py:to_dict() 的 offset 改为读取时用 calculate_offset(latest_time) 实时计算,不再读 offset 列。该列是写入时刻的快照,采集一停摆就整体失真 (库里停在 2026-02-06,offset 却仍显示“当天”)。列保留但已废弃, 不执行 ALTER TABLE DROP COLUMN。 入库语义(db_ingest): - 只有爬虫拿到真实业务时间才更新主表 latest_time,拿不到就保留上一个有效值 (冻结),不再回退到 current_time。 - DeviceHistory 单独用 history_time:主表回答“数据到什么时候”,历史回答 “什么时候采过”。 - 历史表 json_data 改存本次增量切片,不再复制主表那份越滚越大的累积 JSON。 - 主表 json_data 改为覆盖式更新以切断无限膨胀,但保留 APP_OWNED_KEYS (bound_iccid / is_whitelist)—— 这两个键由 /bind_device_card 和 /toggle_whitelist 写入,按原方案直接覆盖会清空所有设备-流量卡绑定。
26 lines
780 B
Python
26 lines
780 B
Python
# services/time_utils.py
|
||
"""
|
||
时间辅助函数。
|
||
|
||
刻意不依赖 flask / db / models,避免被 services.db_ingest 和 routes.api
|
||
互相引用时产生循环导入。
|
||
"""
|
||
from datetime import datetime
|
||
|
||
|
||
def calculate_offset(latest_time_str):
|
||
"""
|
||
计算时间滞后天数
|
||
用于前端展示设备数据是否过时
|
||
"""
|
||
if not latest_time_str or latest_time_str == "N/A":
|
||
return "从未同步"
|
||
try:
|
||
# 兼容处理 2026_01_13 和 2026-01-13 格式
|
||
clean = str(latest_time_str).split()[0].replace('_', '-')
|
||
target = datetime.strptime(clean, "%Y-%m-%d").date()
|
||
diff = (datetime.now().date() - target).days
|
||
return "当天" if diff == 0 else f"滞后 {diff} 天"
|
||
except:
|
||
return "时间解析失败"
|