From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 3FD481FF138 for ; Wed, 04 Feb 2026 16:27:14 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E428D184B6; Wed, 4 Feb 2026 16:27:42 +0100 (CET) From: Lukas Wagner To: pdm-devel@lists.proxmox.com Subject: [PATCH datacenter-manager 3/5] parallel fetcher: add builder and make struct members private Date: Wed, 4 Feb 2026 16:27:21 +0100 Message-ID: <20260204152723.482258-4-l.wagner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260204152723.482258-1-l.wagner@proxmox.com> References: <20260204152723.482258-1-l.wagner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1770218781153 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.037 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 624NDDYVLF2NW776EBDC4IHLCIZEH7NY X-Message-ID-Hash: 624NDDYVLF2NW776EBDC4IHLCIZEH7NY 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: ParallelFetcher could potentially be used quite often in the PDM codebase, so it makes sense to make its usage as convenient as possible. Also, it makes sense to hide its internals as much as possible, so that we can make future changes without modifying the callers. Signed-off-by: Lukas Wagner --- .../tasks/remote_tasks.rs | 9 ++- server/src/parallel_fetcher.rs | 58 ++++++++++++++++--- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/server/src/bin/proxmox-datacenter-api/tasks/remote_tasks.rs b/server/src/bin/proxmox-datacenter-api/tasks/remote_tasks.rs index c71a0894..93a0d05e 100644 --- a/server/src/bin/proxmox-datacenter-api/tasks/remote_tasks.rs +++ b/server/src/bin/proxmox-datacenter-api/tasks/remote_tasks.rs @@ -264,11 +264,10 @@ async fn fetch_remotes( remotes: Vec, cache_state: Arc, ) -> (Vec, NodeFetchSuccessMap) { - let fetcher = ParallelFetcher { - max_connections: MAX_CONNECTIONS, - max_connections_per_remote: CONNECTIONS_PER_PVE_REMOTE, - context: cache_state, - }; + let fetcher = ParallelFetcher::builder(cache_state) + .max_connections(MAX_CONNECTIONS) + .max_connections_per_remote(CONNECTIONS_PER_PVE_REMOTE) + .build(); let fetch_results = fetcher .do_for_all_remote_nodes(remotes.into_iter(), fetch_tasks_from_single_node) diff --git a/server/src/parallel_fetcher.rs b/server/src/parallel_fetcher.rs index f07a2de3..1eded293 100644 --- a/server/src/parallel_fetcher.rs +++ b/server/src/parallel_fetcher.rs @@ -19,9 +19,9 @@ pub const DEFAULT_MAX_CONNECTIONS: usize = 20; pub const DEFAULT_MAX_CONNECTIONS_PER_REMOTE: usize = 5; pub struct ParallelFetcher { - pub max_connections: usize, - pub max_connections_per_remote: usize, - pub context: C, + max_connections: usize, + max_connections_per_remote: usize, + context: C, } pub struct FetchResults { @@ -59,15 +59,59 @@ pub struct NodeResults { pub api_response_time: Duration, } -impl ParallelFetcher { - pub fn new(context: C) -> Self { +/// Builder for the [`ParallelFetcher`] struct. +pub struct ParallelFetcherBuilder { + max_connections: Option, + max_connections_per_remote: Option, + context: C, +} + +impl ParallelFetcherBuilder { + fn new(context: C) -> Self { Self { - max_connections: DEFAULT_MAX_CONNECTIONS, - max_connections_per_remote: DEFAULT_MAX_CONNECTIONS_PER_REMOTE, context, + max_connections: None, + max_connections_per_remote: None, } } + /// Set the maximum number of parallel connections. + pub fn max_connections(mut self, limit: usize) -> Self { + self.max_connections = Some(limit); + self + } + + /// Set the maximum number of parallel connections per remote. + /// + /// This only really affects PVE remotes with multiple cluster members. + pub fn max_connections_per_remote(mut self, limit: usize) -> Self { + self.max_connections_per_remote = Some(limit); + self + } + + /// Build the [`ParallelFetcher`] instance. + pub fn build(self) -> ParallelFetcher { + ParallelFetcher { + max_connections: self.max_connections.unwrap_or(DEFAULT_MAX_CONNECTIONS), + max_connections_per_remote: self + .max_connections_per_remote + .unwrap_or(DEFAULT_MAX_CONNECTIONS_PER_REMOTE), + context: self.context, + } + } +} + +impl ParallelFetcher { + /// Create a [`ParallelFetcher`] with default settings. + pub fn new(context: C) -> Self { + Self::builder(context).build() + } + + /// Create the builder for constructing a [`ParallelFetcher`] with custom settings. + pub fn builder(context: C) -> ParallelFetcherBuilder { + ParallelFetcherBuilder::new(context) + } + pub async fn do_for_all_remote_nodes(self, remotes: A, func: F) -> FetchResults where A: Iterator, -- 2.47.3