Show active transfer count, add SFTP retry resilience, and fix config tab refresh
- Use rclone transferring array to show only active transfers instead of cumulative count; zero out speed when no transfers are active - Add SFTP retry/timeout flags to rclone mount for flaky Tailscale tunnels - Skip auto-refresh on config tab to prevent editor resets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
16d11aa4ef
commit
15f915fbee
@ -70,6 +70,16 @@ pub fn build_mount_args(config: &Config, share: &ShareConfig, rc_port: u16) -> V
|
|||||||
args.push("--transfers".into());
|
args.push("--transfers".into());
|
||||||
args.push(config.writeback.transfers.to_string());
|
args.push(config.writeback.transfers.to_string());
|
||||||
|
|
||||||
|
// SFTP connection resilience: increase retries for flaky tunnels (Tailscale/WireGuard)
|
||||||
|
args.push("--retries".into());
|
||||||
|
args.push("10".into());
|
||||||
|
args.push("--low-level-retries".into());
|
||||||
|
args.push("20".into());
|
||||||
|
args.push("--retries-sleep".into());
|
||||||
|
args.push("1s".into());
|
||||||
|
args.push("--contimeout".into());
|
||||||
|
args.push("30s".into());
|
||||||
|
|
||||||
// Bandwidth limits (only add flag if at least one direction is limited)
|
// Bandwidth limits (only add flag if at least one direction is limited)
|
||||||
let bw = format_bwlimit(&config.bandwidth.limit_up, &config.bandwidth.limit_down);
|
let bw = format_bwlimit(&config.bandwidth.limit_up, &config.bandwidth.limit_down);
|
||||||
if bw != "0" {
|
if bw != "0" {
|
||||||
|
|||||||
@ -16,6 +16,9 @@ pub struct CoreStats {
|
|||||||
pub errors: u64,
|
pub errors: u64,
|
||||||
#[serde(rename = "totalBytes")]
|
#[serde(rename = "totalBytes")]
|
||||||
pub total_bytes: Option<u64>,
|
pub total_bytes: Option<u64>,
|
||||||
|
/// Currently active transfers (present only when transfers are running).
|
||||||
|
#[serde(default)]
|
||||||
|
pub transferring: Vec<serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Response from `vfs/stats`.
|
/// Response from `vfs/stats`.
|
||||||
@ -233,5 +236,22 @@ mod tests {
|
|||||||
assert_eq!(stats.bytes, u64::MAX);
|
assert_eq!(stats.bytes, u64::MAX);
|
||||||
assert_eq!(stats.transfers, 1000000);
|
assert_eq!(stats.transfers, 1000000);
|
||||||
assert_eq!(stats.errors, 999);
|
assert_eq!(stats.errors, 999);
|
||||||
|
assert!(stats.transferring.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_core_stats_with_active_transferring() {
|
||||||
|
let json = r#"{
|
||||||
|
"bytes": 1048576,
|
||||||
|
"speed": 524288.0,
|
||||||
|
"transfers": 5,
|
||||||
|
"errors": 0,
|
||||||
|
"transferring": [
|
||||||
|
{"name": "file1.jpg", "size": 1024, "bytes": 512},
|
||||||
|
{"name": "file2.jpg", "size": 2048, "bytes": 1024}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
let stats: CoreStats = serde_json::from_str(json).unwrap();
|
||||||
|
assert_eq!(stats.transferring.len(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -732,8 +732,9 @@ fn update_status(
|
|||||||
|
|
||||||
// Fetch core stats (speed, transfers)
|
// Fetch core stats (speed, transfers)
|
||||||
if let Ok(core) = rc::core_stats(mc.rc_port) {
|
if let Ok(core) = rc::core_stats(mc.rc_port) {
|
||||||
ss.speed = core.speed;
|
let active = core.transferring.len() as u64;
|
||||||
ss.transfers = core.transfers;
|
ss.speed = if active > 0 { core.speed } else { 0.0 };
|
||||||
|
ss.transfers = active;
|
||||||
ss.errors = core.errors;
|
ss.errors = core.errors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
if (this._timer) { clearInterval(this._timer); this._timer = null; }
|
if (this._timer) { clearInterval(this._timer); this._timer = null; }
|
||||||
},
|
},
|
||||||
refreshTab() {
|
refreshTab() {
|
||||||
if (this.activeTab === 'dashboard' || this.activeTab === 'logs') return;
|
if (this.activeTab === 'dashboard' || this.activeTab === 'logs' || this.activeTab === 'config') return;
|
||||||
let url = '/tabs/' + this.activeTab;
|
let url = '/tabs/' + this.activeTab;
|
||||||
if (this.activeTab === 'shares') {
|
if (this.activeTab === 'shares') {
|
||||||
const el = document.querySelector('#tab-content [x-data]');
|
const el = document.querySelector('#tab-content [x-data]');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user