mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
perf: raise the max allowed concurrent connections per SFTP service (#3466)
This commit is contained in:
parent
2f66561a82
commit
366fca6b10
11 changed files with 56 additions and 21 deletions
|
|
@ -17,10 +17,11 @@ impl Actor for Close {
|
||||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||||
let cmp = &mut cx.core.cmp;
|
let cmp = &mut cx.core.cmp;
|
||||||
if let Some(item) = cmp.selected().filter(|_| opt.submit).cloned() {
|
if let Some(item) = cmp.selected().filter(|_| opt.submit).cloned() {
|
||||||
return act!(complete, cx.core.input, CompleteOpt { item, _ticket: cmp.ticket });
|
return act!(input:complete, cx, CompleteOpt { item, ticket: cmp.ticket });
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp.caches.clear();
|
cmp.caches.clear();
|
||||||
|
cmp.ticket = Default::default();
|
||||||
succ!(render!(mem::replace(&mut cmp.visible, false)));
|
succ!(render!(mem::replace(&mut cmp.visible, false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ impl Actor for Show {
|
||||||
succ!();
|
succ!();
|
||||||
};
|
};
|
||||||
|
|
||||||
cmp.ticket = opt.ticket;
|
|
||||||
cmp.cands = Self::match_candidates(opt.word.as_path(), cache);
|
cmp.cands = Self::match_candidates(opt.word.as_path(), cache);
|
||||||
if cmp.cands.is_empty() {
|
if cmp.cands.is_empty() {
|
||||||
succ!(render!(mem::replace(&mut cmp.visible, false)));
|
succ!(render!(mem::replace(&mut cmp.visible, false)));
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use yazi_fs::{path::clean_url, provider::{DirReader, FileHolder}};
|
||||||
use yazi_macro::{act, render, succ};
|
use yazi_macro::{act, render, succ};
|
||||||
use yazi_parser::cmp::{CmpItem, ShowOpt, TriggerOpt};
|
use yazi_parser::cmp::{CmpItem, ShowOpt, TriggerOpt};
|
||||||
use yazi_proxy::CmpProxy;
|
use yazi_proxy::CmpProxy;
|
||||||
use yazi_shared::{AnyAsciiChar, data::Data, natsort, path::{AsPath, PathBufDyn, PathLike}, scheme::{SchemeCow, SchemeLike}, strand::{AsStrand, StrandLike}, url::{UrlBuf, UrlCow, UrlLike}};
|
use yazi_shared::{AnyAsciiChar, BytePredictor, data::Data, natsort, path::{AsPath, PathBufDyn, PathLike}, scheme::{SchemeCow, SchemeLike}, strand::{AsStrand, StrandLike}, url::{UrlBuf, UrlCow, UrlLike}};
|
||||||
use yazi_vfs::provider;
|
use yazi_vfs::provider;
|
||||||
|
|
||||||
use crate::{Actor, Ctx};
|
use crate::{Actor, Ctx};
|
||||||
|
|
@ -74,11 +74,14 @@ impl Trigger {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (scheme, path) = SchemeCow::parse(s.as_bytes()).ok()?;
|
let (scheme, path) = SchemeCow::parse(s.as_bytes()).ok()?;
|
||||||
let scheme = scheme.zeroed();
|
if path.is_empty() && !sep.predicate(s.bytes().last()?) {
|
||||||
|
return None; // We don't complete a `sftp://test`, but `sftp://test/`
|
||||||
|
}
|
||||||
|
|
||||||
// We don't complete a `~`, but `~/`
|
// Scheme
|
||||||
|
let scheme = scheme.zeroed();
|
||||||
if scheme.is_local() && path.as_strand() == "~" {
|
if scheme.is_local() && path.as_strand() == "~" {
|
||||||
return None;
|
return None; // We don't complete a `~`, but `~/`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Child
|
// Child
|
||||||
|
|
@ -113,7 +116,9 @@ mod tests {
|
||||||
fn test_split() {
|
fn test_split() {
|
||||||
yazi_shared::init_tests();
|
yazi_shared::init_tests();
|
||||||
yazi_fs::init();
|
yazi_fs::init();
|
||||||
compare("", "", "");
|
|
||||||
|
assert_eq!(Trigger::split_url(""), None);
|
||||||
|
assert_eq!(Trigger::split_url("sftp://test"), None);
|
||||||
compare(" ", "", " ");
|
compare(" ", "", " ");
|
||||||
|
|
||||||
compare("/", "/", "");
|
compare("/", "/", "");
|
||||||
|
|
|
||||||
23
yazi-actor/src/input/complete.rs
Normal file
23
yazi-actor/src/input/complete.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use yazi_macro::{act, succ};
|
||||||
|
use yazi_parser::input::CompleteOpt;
|
||||||
|
use yazi_shared::data::Data;
|
||||||
|
|
||||||
|
use crate::{Actor, Ctx};
|
||||||
|
|
||||||
|
pub struct Complete;
|
||||||
|
|
||||||
|
impl Actor for Complete {
|
||||||
|
type Options = CompleteOpt;
|
||||||
|
|
||||||
|
const NAME: &str = "complete";
|
||||||
|
|
||||||
|
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||||
|
let input = &mut cx.input;
|
||||||
|
if !input.visible || input.ticket.current() != opt.ticket {
|
||||||
|
succ!();
|
||||||
|
}
|
||||||
|
|
||||||
|
act!(complete, input, opt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
yazi_macro::mod_flat!(close escape show);
|
yazi_macro::mod_flat!(close complete escape show);
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,10 @@ impl<'a> Executor<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputMode::Insert | InputMode::Replace => {}
|
InputMode::Insert => {
|
||||||
|
on!(complete);
|
||||||
|
}
|
||||||
|
InputMode::Replace => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.app.core.input.execute(cmd)
|
self.app.core.input.execute(cmd)
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ use crate::cmp::CmpItem;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CompleteOpt {
|
pub struct CompleteOpt {
|
||||||
pub item: CmpItem,
|
pub item: CmpItem,
|
||||||
pub _ticket: Id, // FIXME: not used
|
pub ticket: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<CmdCow> for CompleteOpt {
|
impl TryFrom<CmdCow> for CompleteOpt {
|
||||||
|
|
@ -18,7 +18,7 @@ impl TryFrom<CmdCow> for CompleteOpt {
|
||||||
bail!("Invalid 'item' in CompleteOpt");
|
bail!("Invalid 'item' in CompleteOpt");
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self { item, _ticket: c.get("ticket").unwrap_or_default() })
|
Ok(Self { item, ticket: c.get("ticket").unwrap_or_default() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ impl AsyncSeek for File {
|
||||||
SeekFrom::End(n) => SeekState::Blocking(
|
SeekFrom::End(n) => SeekState::Blocking(
|
||||||
n,
|
n,
|
||||||
timeout(
|
timeout(
|
||||||
Duration::from_secs(10),
|
Duration::from_secs(45),
|
||||||
self.session.send_sync(requests::Fstat::new(&self.handle))?,
|
self.session.send_sync(requests::Fstat::new(&self.handle))?,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -198,7 +198,7 @@ impl AsyncWrite for File {
|
||||||
|
|
||||||
if me.flush_rx.is_none() {
|
if me.flush_rx.is_none() {
|
||||||
match Operator::from(&me.session).fsync(&me.handle) {
|
match Operator::from(&me.session).fsync(&me.handle) {
|
||||||
Ok(rx) => me.flush_rx = Some(timeout(Duration::from_secs(10), rx)),
|
Ok(rx) => me.flush_rx = Some(timeout(Duration::from_secs(45), rx)),
|
||||||
Err(Error::Unsupported) => return Poll::Ready(Ok(())),
|
Err(Error::Unsupported) => return Poll::Ready(Ok(())),
|
||||||
Err(e) => Err(e)?,
|
Err(e) => Err(e)?,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ impl ReadDir {
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.session
|
.session
|
||||||
.send_with_timeout(requests::ReadDir::new(&self.handle), Duration::from_mins(5))
|
.send_with_timeout(requests::ReadDir::new(&self.handle), Duration::from_mins(45))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
self.name = match result {
|
self.name = match result {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{io, sync::Arc};
|
use std::{io, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use russh::keys::PrivateKeyWithHashAlg;
|
use russh::keys::PrivateKeyWithHashAlg;
|
||||||
use yazi_config::vfs::ServiceSftp;
|
use yazi_config::vfs::ServiceSftp;
|
||||||
|
|
@ -53,7 +53,14 @@ impl Conn {
|
||||||
use deadpool::managed::PoolError;
|
use deadpool::managed::PoolError;
|
||||||
|
|
||||||
let pool = *super::CONN.lock().entry(self.config).or_insert_with(|| {
|
let pool = *super::CONN.lock().entry(self.config).or_insert_with(|| {
|
||||||
Box::leak(Box::new(deadpool::managed::Pool::builder(self).max_size(5).build().unwrap()))
|
Box::leak(Box::new(
|
||||||
|
deadpool::managed::Pool::builder(self)
|
||||||
|
.runtime(deadpool::Runtime::Tokio1)
|
||||||
|
.max_size(8)
|
||||||
|
.create_timeout(Some(Duration::from_secs(45)))
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
pool.get().await.map_err(|e| match e {
|
pool.get().await.map_err(|e| match e {
|
||||||
|
|
@ -67,9 +74,8 @@ impl Conn {
|
||||||
|
|
||||||
async fn connect(self) -> Result<russh::Channel<russh::client::Msg>, russh::Error> {
|
async fn connect(self) -> Result<russh::Channel<russh::client::Msg>, russh::Error> {
|
||||||
let pref = Arc::new(russh::client::Config {
|
let pref = Arc::new(russh::client::Config {
|
||||||
inactivity_timeout: Some(std::time::Duration::from_secs(30)),
|
inactivity_timeout: Some(std::time::Duration::from_secs(60)),
|
||||||
keepalive_interval: Some(std::time::Duration::from_secs(10)),
|
keepalive_interval: Some(std::time::Duration::from_secs(10)),
|
||||||
nodelay: true,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,6 @@ impl Input {
|
||||||
|
|
||||||
on!(backspace);
|
on!(backspace);
|
||||||
on!(kill);
|
on!(kill);
|
||||||
|
|
||||||
on!(complete);
|
|
||||||
}
|
}
|
||||||
InputMode::Replace => {}
|
InputMode::Replace => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue