From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 2D89B1FF09B for ; Mon, 31 Aug 2026 13:46:07 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id E90FD206C1; Mon, 31 Aug 2026 13:46:06 +0200 (CEST) From: Lukas Wagner To: pdm-devel@lists.proxmox.com subject: SPAM: [PATCH datacenter-manager] api: local/remote tasks: simplify errors/statusfilter logic Date: Mon, 31 Aug 2026 13:45:54 +0200 Message-ID: <20260831114554.831287-1-l.wagner@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1788176744177 X-SPAM-LEVEL: Spam detection results: 3 AWL 0.559 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_DBL_SPAM 5 Contains a spam URL listed in the Spamhaus DBL blocklist [tasks.rs] Message-ID-Hash: IOZ5TEJZV5K7S2H2UEWG6GGGMRTNAOIV X-Message-ID-Hash: IOZ5TEJZV5K7S2H2UEWG6GGGMRTNAOIV X-MailFrom: l.wagner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: `errors` is semantically a subset of `statusfilter`, so we can simplify the code quite a bit if we include the behavior controlled by `errors` into `statusfilter` and then only filter based on the latter. Signed-off-by: Lukas Wagner --- server/src/api/nodes/tasks.rs | 31 +++++++++++++++++++++++-------- server/src/remote_tasks/mod.rs | 26 +++++++++++++++++--------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/server/src/api/nodes/tasks.rs b/server/src/api/nodes/tasks.rs index 1cca3c0a..7f96656a 100644 --- a/server/src/api/nodes/tasks.rs +++ b/server/src/api/nodes/tasks.rs @@ -88,6 +88,16 @@ pub fn list_tasks( statusfilter, } = filters; + let mut statusfilter = statusfilter.unwrap_or_default(); + if errors { + // Contrary to popular belief, `errors` returns more than just errors... + statusfilter.extend([ + TaskStateType::Error, + TaskStateType::Unknown, + TaskStateType::Warning, + ]); + } + let auth_id: Authid = rpcenv .get_auth_id() .context("no authid available")? @@ -147,17 +157,22 @@ pub fn list_tasks( } } - match (&info.state, &statusfilter) { - (Some(_), _) if running => continue, - (Some(TaskState::OK { .. }), _) if errors => continue, - (Some(state), Some(filters)) => { - if !filters.contains(&tasktype(state)) { + if info.state.is_some() && running { + // if there is a task state and we filter by `running`, don't return the task + continue; + } + + if !statusfilter.is_empty() { + if let Some(state) = &info.state { + if !statusfilter.contains(&tasktype(state)) { + // A finished task is filtered out if its state is not contained in + // the list of allowed values continue; } + } else { + // an unfinished task is filtered out if *any* status filter is set + continue; } - (None, _) if errors => continue, - (None, Some(_)) => continue, - _ => {} } if skipped < start as usize { diff --git a/server/src/remote_tasks/mod.rs b/server/src/remote_tasks/mod.rs index bcae7f4c..05a875d6 100644 --- a/server/src/remote_tasks/mod.rs +++ b/server/src/remote_tasks/mod.rs @@ -51,6 +51,16 @@ pub async fn get_tasks( limit => limit as usize, }; + let mut status_filter = filters.statusfilter.unwrap_or_default(); + if filters.errors { + // Contrary to popular belief, `errors` returns more than just errors... + status_filter.extend([ + TaskStateType::Error, + TaskStateType::Unknown, + TaskStateType::Warning, + ]); + } + let returned_tasks = cache .get_tasks(which)? .filter_map(|task| { @@ -140,16 +150,14 @@ pub async fn get_tasks( let state = item.status.as_deref().map(TaskStateType::new_from_str); - match (state, &filters.statusfilter) { - (Some(TaskStateType::OK), _) if filters.errors => return false, - (Some(state), Some(filters)) => { - if !filters.contains(&state) { - return false; - } + if !status_filter.is_empty() { + if let Some(state) = &state { + // Only apply status filters against finished tasks. + return status_filter.contains(state); + } else { + // If status filters are set, a running task should not be returned. + return false; } - (None, Some(_)) => return false, - (None, _) if filters.errors => return false, - _ => {} } true -- 2.47.3