refactor: move upload fetch timeout helper

This commit is contained in:
lix-2026
2026-05-25 00:59:49 +08:00
parent e54f255690
commit e1484f4cc0
4 changed files with 39 additions and 2 deletions
@@ -6,7 +6,7 @@
## 1. 目标 ## 1. 目标
`3-19` 已归档的基础上,继续把仍留在 Rust inline / 主壳大 runtime 中的浏览器行为切成可审计模块。Codex 维护本文件作为事实源,Reasonix 只承接短批次审计、窄范围实现或浏览器 smoke;每批最多 2 个 worker。 `3-19` 已归档的基础上,继续把仍留在 Rust inline / 主壳大 runtime 中的浏览器行为切成可审计模块。Codex 维护本文件作为事实源,Reasonix 只承接短批次审计、窄范围实现或浏览器 smoke;每批最多 4 个 worker。
## 2. 本轮边界 ## 2. 本轮边界
@@ -65,3 +65,9 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 2026-05-25Codex 创建本续跑事实源。 - 2026-05-25Codex 创建本续跑事实源。
- 2026-05-25:修正执行约束:本文件遵循当前 goal 的“每批最多 2 个 worker”,不再沿用早期草稿中的 4 worker 并行方案。 - 2026-05-25:修正执行约束:本文件遵循当前 goal 的“每批最多 2 个 worker”,不再沿用早期草稿中的 4 worker 并行方案。
- 2026-05-25:下一批只派发 Worker Blocal upload / filetree 下一刀只读审计);Worker A/C/D 暂缓。 - 2026-05-25:下一批只派发 Worker Blocal upload / filetree 下一刀只读审计);Worker A/C/D 暂缓。
- 2026-05-25Reasonix local upload / filetree 只读审计尝试未产生 `result.json` / `process-handoff`,且运行期间出现额外 Batch A2 runner,主控已终止进程;该结果不作为正式 handoff 采纳。
- 可参考的 transcript 结论:`fetchWithTimeout` 是低风险纯工具函数,可先迁入 `local-upload-runtime.js``uploadFileToMediaAsset` / `uploadFilesWithResolvedTarget` / `insertUploadedAssetIntoEditor` 仍与 API、editor 插入和 snapshot refresh 耦合,暂不迁。
- 2026-05-25Codex 主控直接完成低风险切片:`local-upload-runtime.js` 新增并导出 `fetchWithTimeout``layout.rs` 的 inline `fetchWithTimeout` 先委托 runtime,保留原 fallback。
- 修改:`rust/crates/mnote-web/browser/local-upload-runtime.js``rust/crates/mnote-web/src/ssr/pages/layout.rs`
- 已验证:`node --check rust/crates/mnote-web/browser/local-upload-runtime.js``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web mnote_browser_runtime_assets_are_explicitly_mounted -- --test-threads=1``cargo test --manifest-path rust/Cargo.toml -p mnote-web local_upload_runtime_contains_editor_upload_context_helpers -- --test-threads=1`
- 未完成:`insertUploadedAssetIntoEditor``uploadFileToMediaAsset``uploadFilesWithResolvedTarget` 仍未迁出。
@@ -67,4 +67,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 已迁函数:`node_is_within_root``active_editor_text_selection``has_active_text_selection``selection_summary``selection_has_rich_marks` - 已迁函数:`node_is_within_root``active_editor_text_selection``has_active_text_selection``selection_summary``selection_has_rich_marks`
- 未迁:`SelectionPayload``selection_payload``send_selection_state*``selection_event_payload`,原因是仍依赖 bridge event、`HoveredBlockState` 和 runtime block id 边界。 - 未迁:`SelectionPayload``selection_payload``send_selection_state*``selection_event_payload`,原因是仍依赖 bridge event、`HoveredBlockState` 和 runtime block id 边界。
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``task488``task489`、CodeGraph pending 0。 - 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``task488``task489`、CodeGraph pending 0。
- 2026-05-25下一批只派发 Worker Boverlay / block menu 只读审计);Worker C/D 暂缓,避免超过每批最多 2 个 worker 的 goal 约束 - 2026-05-25执行口径修正:用户指出只读审计推进过慢,后续 B/C/D 应使用独立 worktree 产出候选 patch,而不是只读审计;每批最多 4 个 worker。
- 2026-05-25Reasonix runner 异常:后续实现 run 未写 `result.json``process-handoff.md/json`,部分 transcript 停在工具调用阶段;Codex 不采纳其文字结论,只复核实际 diff。
- 2026-05-25Reasonix overlay / block menu 只读审计尝试未产生 `result.json` / `process-handoff`,且运行期间出现额外 Batch A2 runner,主控已终止进程;该结果不作为正式 handoff 采纳。
- transcript 只显示探索过程,未形成函数归属表;下一次应改为更窄的单问题只读任务,例如只审计 `floating_toolbar_anchor_from_selection` / `sync_text_selection_overlay` 能否迁入 `overlays.rs`
@@ -124,6 +124,28 @@ function openEditorUploadFilePicker(detail, deps) {
input.click(); input.click();
} }
async function fetchWithTimeout(input, init, timeoutMs, label) {
var controller = typeof AbortController === 'function' ? new AbortController() : null;
var timer = 0;
try {
if (controller) {
timer = window.setTimeout(function() {
controller.abort();
}, Math.max(1000, Number(timeoutMs) || 15000));
}
var nextInit = Object.assign({}, init || {});
if (controller) nextInit.signal = controller.signal;
return await fetch(input, nextInit);
} catch (error) {
if (error && error.name === 'AbortError') {
throw new Error((label || '请求') + '超时');
}
throw error;
} finally {
if (timer) window.clearTimeout(timer);
}
}
function localAssetOpenUrl(asset, download, context) { function localAssetOpenUrl(asset, download, context) {
if (!isLocalUploadedAsset(asset)) return ''; if (!isLocalUploadedAsset(asset)) return '';
var rootUri = String(context && context.rootUri || asset && (asset.rootUri || asset.root_uri) || '').trim() || currentRootUri(); var rootUri = String(context && context.rootUri || asset && (asset.rootUri || asset.root_uri) || '').trim() || currentRootUri();
@@ -252,6 +274,7 @@ window.__mnoteLocalUploadRuntime = {
resolveEditorUploadContext: resolveEditorUploadContext, resolveEditorUploadContext: resolveEditorUploadContext,
editorRootFromUploadOptions: editorRootFromUploadOptions, editorRootFromUploadOptions: editorRootFromUploadOptions,
openEditorUploadFilePicker: openEditorUploadFilePicker, openEditorUploadFilePicker: openEditorUploadFilePicker,
fetchWithTimeout: fetchWithTimeout,
localAssetOpenUrl: localAssetOpenUrl, localAssetOpenUrl: localAssetOpenUrl,
uploadedAssetType: uploadedAssetType, uploadedAssetType: uploadedAssetType,
fileTreeIconKindForFileName: fileTreeIconKindForFileName, fileTreeIconKindForFileName: fileTreeIconKindForFileName,
@@ -3879,6 +3879,10 @@ const SIDEBAR_TREE_JS: &str = r##"
} }
async function fetchWithTimeout(input, init, timeoutMs, label) { async function fetchWithTimeout(input, init, timeoutMs, label) {
var runtimeFn = localUploadRuntimeFunction('fetchWithTimeout');
if (runtimeFn) {
return await runtimeFn(input, init || {}, timeoutMs, label);
}
var controller = typeof AbortController === 'function' ? new AbortController() : null; var controller = typeof AbortController === 'function' ? new AbortController() : null;
var timer = 0; var timer = 0;
try { try {
@@ -10930,6 +10934,7 @@ mod tests {
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function resolveEditorUploadContext")); assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function resolveEditorUploadContext"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function editorRootFromUploadOptions")); assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function editorRootFromUploadOptions"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function openEditorUploadFilePicker")); assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function openEditorUploadFilePicker"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function fetchWithTimeout"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("uploadFilesWithResolvedTarget")); assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("uploadFilesWithResolvedTarget"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("__mnoteLastEditorUploadRoot")); assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("__mnoteLastEditorUploadRoot"));
} }