Skip to content

Commit 91b05f1

Browse files
bobleerbitfun-aiGCWing
authored
fix(remote-transfer): keep file transfers running instead of timing out (#3235)
* fix(remote-transfer): keep file transfers running instead of timing out Every remote file command inherited one 30s frontend request deadline, so a slow-but-healthy transfer was reported as "Request timeout" while the host kept transferring. Transfers now stream instead of buffering whole files, stage the destination and publish it only after the bytes completed, and carry one cancellable transfer id from the progress card to the backend so a stop reaches the operation it displays. Co-authored-by: OpenBitFun <318544290+bitfun-ai@users.noreply.github.com> * fix(remote-transfer): align installer CI and cancellation paths * fix(remote-transfer): finish cancelled upload sessions cleanly --------- Co-authored-by: OpenBitFun <318544290+bitfun-ai@users.noreply.github.com> Co-authored-by: GCWing <gcwing@foxmail.com>
1 parent 42e376b commit 91b05f1

20 files changed

Lines changed: 1606 additions & 289 deletions

File tree

‎OpenBitFun-Installer/src-tauri/Cargo.toml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ path = "src/main.rs"
1515

1616
[build-dependencies]
1717
tauri-build = { version = "=2.6.3", features = [] }
18+
# This standalone app does not commit a Cargo.lock. Keep the Tauri build-time
19+
# crates aligned with the patched 2.11 runtime instead of resolving 2.7/2.10.
20+
tauri-codegen = "=2.6.3"
1821
zip = "0.6"
1922

2023
[dependencies]
2124
tauri = { version = "=2.11.5", features = [] }
25+
tauri-macros = "=2.6.3"
26+
tauri-plugin = "=2.6.3"
27+
tauri-utils = "=2.9.3"
2228
tauri-plugin-dialog = "=2.7.3"
2329
serde = { version = "1", features = ["derive"] }
2430
serde_json = "1"

‎docs/architecture/remote-workspace-transport.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,29 @@ through the destination to preserve existing links and permissions. The final
183183
write is not an atomic transaction against other writers; interruption during
184184
that phase can have a partial or unknown outcome.
185185

186+
Both providers publish an upload only after the transfer completed: the SFTP
187+
path streams into a same-directory `<hidden data dir>-upload-<id>.tmp` sibling
188+
and renames it over the destination, the container command does the same after
189+
its size check, and a downloaded file is staged beside its local destination
190+
the same way. A failed or cancelled transfer therefore leaves any previous
191+
destination unchanged, and staging temporaries are removed when the owning side
192+
can still reach the path. For directory transfers, files already published and
193+
directories already created remain when a later entry fails or is stopped.
194+
Because a published upload replaces its destination
195+
rather than writing through it, the result takes the staging file's mode and
196+
ownership, and a replaced symlink or hard link is not followed; that is what
197+
distinguishes a transfer from a workspace tool write above. A hard kill between
198+
staging and commit can leave one orphaned temporary, which the container
199+
commands sweep by age and the SFTP path leaves to the user.
200+
201+
The desktop upload and download commands opt out of the shared 30-second
202+
controller deadline when their caller provides a progress and stop surface.
203+
Every SFTP request retains its own response timeout, the SSH transport drops a
204+
stalled connection, and the transfer ends when it completes, fails, or is
205+
stopped. File reads, writes, listings, and transfers without a stop surface keep
206+
the default controller deadline. A short deadline on a stoppable transfer only
207+
reported a slow-but-healthy operation as failed while the host kept working.
208+
186209
Directory and stat records use NUL-separated fields. File names containing
187210
newlines or the delimiters used by older implementations remain round-trippable.
188211
The records are decoded only after the full byte stream is assembled; invalid

0 commit comments

Comments
 (0)