[pdm-devel] [PATCH datacenter-manager v2] ui: resource tree: use AsyncAbortGuard to cancel obsolete pending loads
Dominik Csapak
d.csapak at proxmox.com
Fri Apr 18 09:46:47 CEST 2025
Currently, if a new serach term is given, a new load will occur if the
INPUT_BUFFER_MS time is reached. Any old in-flight API requests are not
canceled, and might still arrive.
To prevent that, use an AsyncAbortGuard so the old load will be aborted
whenever it is overwritten.
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
changes from v1:
* use AsyncAbortGuard instead of AsyncPool, since that's the correct
abstraction here.
* introduce a new Msg variant, so that we can overwrite the AsyncAbortGuard
in the update method
replaces:
https://lore.proxmox.com/pdm-devel/20250416113232.2488103-1-d.csapak@proxmox.com/
ui/src/widget/resource_tree.rs | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/ui/src/widget/resource_tree.rs b/ui/src/widget/resource_tree.rs
index feff308..ddfd7cb 100644
--- a/ui/src/widget/resource_tree.rs
+++ b/ui/src/widget/resource_tree.rs
@@ -18,6 +18,7 @@ use pwt::{
},
ActionIcon, Column, Container, Fa, Panel, Progress, Row, Tooltip,
},
+ AsyncAbortGuard,
};
use pwt_macros::{builder, widget};
@@ -88,6 +89,7 @@ async fn load_resources(search_term: String) -> Result<Vec<RemoteResources>, Err
}
pub enum Msg {
+ LoadRequest,
Load,
LoadResult(Result<Vec<RemoteResources>, Error>),
RemoteListChanged(RemoteList),
@@ -101,6 +103,7 @@ pub struct PdmResourceTree {
_context_listener: ContextHandle<RemoteList>,
selection: Selection,
_load_timeout: Option<Timeout>,
+ _load_guard: Option<AsyncAbortGuard>,
}
impl PdmResourceTree {}
@@ -117,7 +120,7 @@ impl Component for PdmResourceTree {
.expect("No Remote list context provided");
if !props.search_only || !props.search_term.is_empty() {
- ctx.link().clone().send_message(Msg::Load);
+ ctx.link().clone().send_message(Msg::LoadRequest);
}
let store = TreeStore::new().view_root(false);
@@ -131,25 +134,32 @@ impl Component for PdmResourceTree {
_context_listener,
selection,
_load_timeout: None,
+ _load_guard: None,
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
- Msg::Load => {
+ Msg::LoadRequest => {
let props = ctx.props();
let link = ctx.link().clone();
- let search_term = props.search_term.clone();
- if props.search_only && !search_term.is_empty() {
+ if props.search_only && !props.search_term.is_empty() {
self._load_timeout = Some(Timeout::new(INPUT_BUFFER_MS, move || {
- link.send_future(async move {
- Msg::LoadResult(load_resources(search_term).await)
- });
+ link.send_message(Msg::Load);
}));
self.loading = true;
}
true
}
+ Msg::Load => {
+ let props = ctx.props();
+ let link = ctx.link().clone();
+ let search_term = props.search_term.clone();
+ self._load_guard = Some(AsyncAbortGuard::spawn(async move {
+ link.send_message(Msg::LoadResult(load_resources(search_term).await))
+ }));
+ false
+ }
Msg::LoadResult(res) => {
match res {
Ok(result) => {
@@ -189,7 +199,7 @@ impl Component for PdmResourceTree {
let reload = self.remote_list.len() != list.len();
self.remote_list = list;
if reload && !self.remote_list.is_empty() {
- ctx.link().send_message(Msg::Load);
+ ctx.link().send_message(Msg::LoadRequest);
}
true
}
@@ -200,7 +210,7 @@ impl Component for PdmResourceTree {
let props = ctx.props();
if props.search_term != old_props.search_term {
if !props.search_only || !props.search_term.is_empty() {
- ctx.link().clone().send_message(Msg::Load);
+ ctx.link().clone().send_message(Msg::LoadRequest);
} else if props.search_term.is_empty() {
// clear grid
ctx.link()
--
2.39.5
More information about the pdm-devel
mailing list