Repository navigation
feat(download): 下载 weg.fan 镜像前先制作镜像并展示进度 - #92
Open
std-external wants to merge 2 commits into
Open
std-external wants to merge 2 commits into
std-external wants to merge 2 commits into
Conversation
下载镜像文件时不再直接拉下载接口等服务器现做镜像(会长时间阻塞),
而是先 POST /api/v2/mirror/start/{fileId},再轮询
/api/v2/mirror/status/{fileId} 把服务端制作进度显示在下载管理里,
进度满后再下载。
只对 weg.fan 镜像的下载地址生效(gamebanana-files/{source} 与
files/{fileId} 两个前缀),0x0a.de、GameBanana 直连等其它来源完全保持
现状。制作镜像失败(网络/超时/文件不存在)时记录日志并回退到原来的直连
下载,不会因为镜像新接口挂了就下不了东西。
按 review 意见去掉兜底:/start 或 /status 失败、文件未收录、轮询超时 都让这次下载进入失败状态,理由(制作镜像失败:<原始错误>)显示在下载管理 里,用户可以用现有的「重试」按钮重走一遍制作流程,不再静默换成直连下载。 取消语义不变:取消仍然进入已取消而不是失败。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
weg.fan 镜像下载前会先由服务器现制作镜像文件,直接拉下载接口要一直等到镜像做好才能拿到数据,界面上就是「卡在 0%」。群主 @WEGFan 提出的流程:先
start让服务器开始制作,轮询status把进度显示在下载管理里,进度满了再下载,避免阻塞。参考实现:WEGFan/Celeste-Mod-China-MirrorModules/ChinaMirror.cs#L458(PrepareFile)。接口契约(已在 celeste.weg.fan 上实测)
fileId的来历:CeleMod 用的下载地址是https://celeste.weg.fan/api/v2/download/gamebanana-files/{source},服务器 302 到https://celeste.weg.fan/api/v2/download/files/{fileId},fileId就是后者路径里的雪花 id(与 ChinaMirror 用 HEAD 读Location的做法一致)。已经是files/{fileId}形式的地址则直接取 id。HEAD /api/v2/download/gamebanana-files/{source}(不跟随重定向)302 Location: .../api/v2/download/files/590041115247004037POST /api/v2/mirror/start/{fileId}{"data":null,"code":200,"message":"OK"};未知文件code:10002 "文件未找到"GET /api/v2/mirror/status/{fileId}{"data":{"downloadProgress":{"current":55695,"total":10246734},"uploadProgress":{"current":0,"total":10246734}},"code":200,"message":"OK"}GET /api/v2/download/files/{fileId}302 → https://celeste-mirror-cdn-2.wegfan.com/...(支持Range,206)状态机:
downloadProgress是服务器从源站拉取文件,uploadProgress是写入镜像缓存;两者current == total才算制作完成。沿用 ChinaMirror 的做法:uploadProgress.current > 0时认为下载阶段已完成(否则最后一段可能因为计数滞后一直等),只有current == total才继续下载。轮询间隔 200ms;超时沿用参考实现:还没拿到任何进度(
total == 0)超过 30s,或已有进度后停滞超过 10s 就放弃制作,另有 600s 总兜底。顺带一提:
/api/v1/mirror/status?type=&fileName=现在会 302 到/api/v2/mirror/status/{fileId},/start/{fileId}就是 v2 的形式,所以这里直接实现 v2。实现
后端(Rust):
src-tauri/src/wegfan.rs:新增镜像制作客户端。prepare_mirror()(:205)解析 fileId →start→ 轮询status→ 返回files/{fileId}下载地址;combined_progress()(:131)合并两段进度;mirror_prepare_stalled()判定超时。HTTP 用 ureq,超时约定与下载 agent 一致(connect/read/write 各 30s,见 fix(download): 下载链路走 ureq 自带的环境代理 + 补上读写超时 #84),并跟随环境代理;只为读 302 关掉重定向跟随。src-tauri/src/backend.rs:prepare_mirror_before_download()(:2832)在下发任务线程里、真正下载之前调用它,进度通过新的DownloadWorkerMessage::Preparing(:2768)上报;ModTaskInfo增加mirror_preparing字段(:2461)。stores/download.ts把mirror_preparing映射成mirrorPreparing(:22 / :225 / :408),DownloadList.tsx的stateLabel()(:94)在该状态下显示「制作镜像中」+ 服务端百分比 + 进度条(tonepreparing,DownloadList.scss里加了一条配色),不再像卡住。只对 wegfan 生效的开关点
wegfan.rs:96的mirror_file_id()只认https://celeste.weg.fan/api/v2/download/gamebanana-files/与.../api/v2/download/files/两个前缀,其余 URL(0x0a.de、GameBanana 直连、用户自定义 URL)返回Ok(None),不产生任何请求,走原来的下载流程。单测only_weg_fan_download_urls_are_prepared锁住这一点。失败、超时与重试(按 review 意见:制作镜像失败直接报错,不退回直连)
backend.rs:2840的resolve_download_url():prepare_mirror报错(/start请求失败、/status接口不可用、文件未收录code 10002、轮询超时)时,任务直接置为失败,不会静默换成直连下载。mirror_prepare_failure()(backend.rs:2834)拼成「制作镜像失败:<原始错误>」,原始错误会说明是哪一步坏了(Failed to query mirror status of {fileId}: ...之类),界面显示在该行下方。DownloadList.tsx里state === "failed"且source存在时的现有replay动作),点重试会重新走一遍start+ 轮询。超时阈值仍与 ChinaMirror 一致:没有任何进度(total == 0)超过 30s、已有进度后停滞超过 10s,另有 600s 总上限。mirror_file_id()就返回Ok(None),resolve_download_url()原样返回,其它镜像与直连的下载路径一个字都没动(download_mirror_tests::non_mirror_urls_are_downloaded_directly锁住)。Download canceled、任务进入「已取消」而不是失败,重试/重下走原有路径(cancelDownload→ cancel flag)。验证
start→ 进度从 0 涨到 100% 的轮询过程)。cargo test --lib:119 passed(含新增 6 个单测:只在 wegfan URL 上生效、fileId 解析、进度合并、超时判定、非镜像地址直连不受影响、失败原因文案)。cargo fmt --check干净,pnpm typecheck干净。(改完 review 意见后这三个都重跑过。)files/{fileId}支持 Range(206),多线程下载不受影响。未验证
与其它 PR 的关系
src/celemod-ui/src/stores/download.ts、src/celemod-ui/src/components/DownloadList.tsx与 #90(下载卡住/重下)改到同一批文件;本 PR 的改动是纯增量(各加一行映射 + 一个状态分支),如果 #90 先合并我来 rebase。来源:Celeste Coders 群,@WEGFan 提出。