fix: 返回键失效的根因 + 同步页重做 + 连接池会永久阻塞线程
返回键
- 根因是 Framework7 的页面过渡由动画事件驱动:push 时把 allowPageChange
置 false,等动画报告结束再恢复。这个报告不来,路由就永久卡住,之后每次
导航都被静默丢弃,back() 还会把上一页重建一份而不是弹出。
实测对照:navigate({animate:false}) 前后状态完全正确,带动画则必卡。
因此关掉页面过渡动画——导航同步完成,处处正确。动效改由内容承担
(卡片入场、hero 揭示、顶部进度条),这个取舍里正确性优先。
- Screen 的返回改为显式 handler,先清掉残留过渡状态再 back(),
不依赖路由自己的闸门。注意只清视图上的 router-transition 类:
页面自身的 page-previous 是 F7 判断「回到哪一页」的依据,
一并清掉会导致重建出一个重复的页面(中途踩过这个坑)。
同步页
- .btn 系列样式原本只定义在 pages/Pages.css,而那个文件只被一个没有路由的
遗留页面引用,所以真实页面上按钮全都退化成 Framework7 的默认样式——
就是你看到的三条链接。样式移进每个界面都会加载的 Screen.css。
- 主次分明:一个填充主按钮 + 两个带副标题的次按钮;补上「同步会取哪些数据」
说明,页面不再是一大片空白。
- 进度条显示当前阶段(每日数据 2026-08-01 / 运动详情 12/174 / 身体成分…),
原来只有「0 / 730 天」,几分钟里完全看不出在做什么。
后端
- MariaDB 连接池:_mariadb_release 用的是阻塞 put(),而队列 maxsize=10,
_mariadb_acquire 在池空时又会新建连接。并发超过 10 之后,归还的线程会
永久停在 put() 上,请求就此挂死。改为 put_nowait,多出来的连接直接关闭。
- 进程重启会带走同步线程却留下 status=syncing 的行,界面上是一个永远不动
的进度条,还拒绝开始新同步。启动时清理。
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -68,9 +68,23 @@ def get_sync_status(user_id):
|
||||
"progressCurrent": row.get("progress_current"),
|
||||
"progressTotal": row.get("progress_total"),
|
||||
"startedAt": row.get("started_at"),
|
||||
"stage": row.get("stage"),
|
||||
}
|
||||
|
||||
|
||||
def reset_stale_syncs():
|
||||
"""Clear a "syncing" status left behind by a process that went away.
|
||||
|
||||
The status lives in the database but the work lives in a thread. A restart
|
||||
(or a crash) takes the thread and leaves the row, so the UI shows a
|
||||
progress bar that will never move and refuses to start a new sync.
|
||||
"""
|
||||
execute(
|
||||
"UPDATE sync_status SET status = 'idle', stage = NULL "
|
||||
"WHERE status = 'syncing'"
|
||||
)
|
||||
|
||||
|
||||
class MFARequired(RuntimeError):
|
||||
"""Raised when a password login needs a code this process cannot obtain."""
|
||||
|
||||
@@ -761,6 +775,7 @@ def sync_data(user_id, creds, days=None, client=None):
|
||||
_set_sync_status(
|
||||
user_id, "syncing", now,
|
||||
records_synced=0, progress_current=0, progress_total=days,
|
||||
stage="连接 Garmin",
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -809,10 +824,13 @@ def sync_data(user_id, creds, days=None, client=None):
|
||||
_set_sync_status(
|
||||
user_id, "syncing", now,
|
||||
records_synced=days_synced, progress_current=i + 1,
|
||||
progress_total=days,
|
||||
progress_total=days, stage=f"每日数据 {date_str}",
|
||||
)
|
||||
|
||||
activities_synced = 0
|
||||
_set_sync_status(user_id, "syncing", now, records_synced=days_synced,
|
||||
progress_current=days, progress_total=days,
|
||||
stage="运动记录")
|
||||
try:
|
||||
activities_synced = _sync_activities(
|
||||
client, user_id, start_date, today.isoformat()
|
||||
@@ -824,13 +842,23 @@ def sync_data(user_id, creds, days=None, client=None):
|
||||
# opening one later is a local read.
|
||||
details_synced = 0
|
||||
try:
|
||||
details_synced = sync_activity_details(client, user_id)
|
||||
details_synced = sync_activity_details(
|
||||
client, user_id,
|
||||
on_progress=lambda d, n: _set_sync_status(
|
||||
user_id, "syncing", now, records_synced=days_synced,
|
||||
progress_current=days, progress_total=days,
|
||||
stage=f"运动详情 {d}/{n}"),
|
||||
)
|
||||
except Exception as e:
|
||||
day_errors.append(f"activity_details: {describe(e)}")
|
||||
|
||||
# Everything else Garmin holds: body composition, blood pressure, race
|
||||
# predictions, challenges and devices. Account-wide, so once per sync.
|
||||
extra_counts = {}
|
||||
stage_names = {
|
||||
"bodyComposition": "身体成分", "bloodPressure": "血压",
|
||||
"racePredictions": "成绩预测", "challenges": "挑战赛", "devices": "设备",
|
||||
}
|
||||
for name, call in (
|
||||
("bodyComposition",
|
||||
lambda: extras.sync_body_composition(client, user_id, start_date,
|
||||
@@ -843,6 +871,9 @@ def sync_data(user_id, creds, days=None, client=None):
|
||||
("challenges", lambda: extras.sync_challenges(client, user_id)),
|
||||
("devices", lambda: extras.sync_devices(client, user_id)),
|
||||
):
|
||||
_set_sync_status(user_id, "syncing", now, records_synced=days_synced,
|
||||
progress_current=days, progress_total=days,
|
||||
stage=stage_names.get(name, name))
|
||||
try:
|
||||
extra_counts[name] = call()
|
||||
except Exception as e: # noqa: BLE001 - one section must not fail the sync
|
||||
@@ -871,7 +902,7 @@ def sync_data(user_id, creds, days=None, client=None):
|
||||
|
||||
_set_sync_status(
|
||||
user_id, "idle", now, records_synced=days_synced,
|
||||
progress_current=days, progress_total=days,
|
||||
progress_current=days, progress_total=days, stage=None,
|
||||
last_error="; ".join(day_errors[:3]) if day_errors else None,
|
||||
)
|
||||
message = (
|
||||
|
||||
Reference in New Issue
Block a user