[yew-devel] [PATCH yew-comp 2/2] tasks: don't add entries we already loaded
Dominik Csapak
d.csapak at proxmox.com
Wed May 7 16:38:00 CEST 2025
If there is a new task in between loads due to scrolling, we got
old tasks from the api that we already loaded.
This happens because:
* tasks are sorted descending by their start time
* we initially request up to 500 from start 0
* we save the amount of tasks there are
* on a new load due to scrolling, we set start to the amount
of tasks knew of -> if there are new tasks now, the start offset
we sent would be too low
To fix this, skip the amount of tasks in the list that were added in the
meantime, which is the new total minus the new total.
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
ideally we could implement a kind of cursor for our tasks, so that
this scenario would not happen, but I'm not sure if this is feasible
alternatively/additionally we could implement some key constraints
for datastores, or use a Store with a HashMap instead of a vector
(we'd have to do the ordering manually in this case though, which
might be a big overhead for big task lists..)
src/tasks.rs | 44 +++++++++++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/src/tasks.rs b/src/tasks.rs
index 3c531c1..ac8d1c5 100644
--- a/src/tasks.rs
+++ b/src/tasks.rs
@@ -95,7 +95,8 @@ pub enum ViewDialog {
pub enum Msg {
Redraw,
ToggleFilter,
- LoadBatch(u64), // start
+ LoadBatch(u64), // start
+ LoadFinished(Option<u64>, Vec<TaskListItem>), // total
UpdateFilter,
ShowTask,
}
@@ -109,6 +110,7 @@ pub struct ProxmoxTasks {
last_filter: serde_json::Value,
load_timeout: Option<Timeout>,
columns: Rc<Vec<DataTableHeader<TaskListItem>>>,
+ total: Option<u64>,
}
impl ProxmoxTasks {
@@ -192,6 +194,7 @@ impl LoadableComponent for ProxmoxTasks {
start: 0,
load_timeout: None,
columns: Self::columns(ctx),
+ total: None,
}
}
@@ -206,8 +209,6 @@ impl LoadableComponent for ProxmoxTasks {
None => format!("/nodes/{nodename}/tasks"),
};
- let store = self.store.clone();
-
let form_context = self.filter_form_context.read();
let mut filter = form_context.get_submit_data();
@@ -234,13 +235,11 @@ impl LoadableComponent for ProxmoxTasks {
filter["start"] = start.into();
filter["limit"] = BATCH_LIMIT.into();
+ let link = ctx.link().clone();
Box::pin(async move {
- let mut data: Vec<_> = crate::http_get(&path, Some(filter)).await?;
- if start == 0 {
- store.write().set_data(data);
- } else {
- store.write().append(&mut data);
- }
+ let response = crate::http_get_full(&path, Some(filter)).await?;
+ let total = response.attribs.get("total").and_then(|v| v.as_u64());
+ link.send_message(Msg::LoadFinished(total, response.data));
Ok(())
})
}
@@ -279,6 +278,33 @@ impl LoadableComponent for ProxmoxTasks {
}));
false
}
+ Msg::LoadFinished(total, mut data) => {
+ let old_total = self.total.take();
+ self.total = total;
+ if self.start == 0 {
+ self.store.write().set_data(data);
+ } else {
+ // if new elements were added at the front, we need to skip as many from the
+ // newly gathered list, otherwise we have duplicate items
+ match (old_total, self.total) {
+ (Some(old), Some(new)) if new > old => {
+ let to_skip = (new - old) as usize;
+
+ if to_skip <= data.len() {
+ data.drain(..to_skip);
+ }
+ }
+ _ => {}
+ };
+
+ if data.is_empty() {
+ return false;
+ } else {
+ self.store.write().append(&mut data);
+ }
+ }
+ true
+ }
Msg::ShowTask => {
if let Some(on_show_task) = &ctx.props().on_show_task {
let selected_item = self
--
2.39.5
More information about the yew-devel
mailing list