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 0904A1FF14F for ; Fri, 08 May 2026 17:04:14 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id BD0591C3F6; Fri, 8 May 2026 17:04:13 +0200 (CEST) From: Lukas Wagner To: pdm-devel@lists.proxmox.com Subject: [PATCH datacenter-manager 2/4] add pdm_cache cache as a specialized wrapper around the namespaced cache Date: Fri, 8 May 2026 17:03:28 +0200 Message-ID: <20260508150330.363622-3-l.wagner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260508150330.363622-1-l.wagner@proxmox.com> References: <20260508150330.363622-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: 1778252507092 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.054 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 URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [proxmox-datacenter-privileged-api.rs,lib.rs] Message-ID-Hash: TXNWDEURVKMPQUW2ENNBR6ERMBUN34ZN X-Message-ID-Hash: TXNWDEURVKMPQUW2ENNBR6ERMBUN34ZN 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: This is a thin wrapper around the previously introduced namespaced key-value cache, but introducing PDM-specific concepts. Instead of the higher-level read/write methods for locking a namespace, this wrapper provides {read,write}_remote and {read,write}_global, for accessing remote-specific and globally cached values. The cache-namespaces are 'global' and 'remote-'. The base directory for the cache is /var/cache/proxmox-datacenter-manager/cache Signed-off-by: Lukas Wagner --- Notes: Not sure about the base directory /var/cache/proxmox-datacenter-manager/cache Maybe 'api-cache' could be a nicer fit, since realistically, we probably only ever cache API responses and aggregations thereof? .../bin/proxmox-datacenter-privileged-api.rs | 7 ++ server/src/lib.rs | 1 + server/src/pdm_cache.rs | 69 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 server/src/pdm_cache.rs diff --git a/server/src/bin/proxmox-datacenter-privileged-api.rs b/server/src/bin/proxmox-datacenter-privileged-api.rs index 6b490f2b..6e8ba611 100644 --- a/server/src/bin/proxmox-datacenter-privileged-api.rs +++ b/server/src/bin/proxmox-datacenter-privileged-api.rs @@ -102,6 +102,13 @@ fn create_directories() -> Result<(), Error> { 0o755, )?; + pdm_config::setup::mkdir_perms( + concat!(pdm_buildcfg::PDM_CACHE_DIR_M!(), "/cache"), + api_user.uid, + api_user.gid, + 0o755, + )?; + server::jobstate::create_jobstate_dir()?; Ok(()) diff --git a/server/src/lib.rs b/server/src/lib.rs index 0b7642ab..5e8c0b64 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -9,6 +9,7 @@ pub mod jobstate; pub mod metric_collection; pub mod namespaced_cache; pub mod parallel_fetcher; +pub mod pdm_cache; pub mod remote_cache; pub mod remote_tasks; pub mod remote_updates; diff --git a/server/src/pdm_cache.rs b/server/src/pdm_cache.rs new file mode 100644 index 00000000..a7370632 --- /dev/null +++ b/server/src/pdm_cache.rs @@ -0,0 +1,69 @@ +use std::{ + path::{Path, PathBuf}, + sync::LazyLock, + time::Duration, +}; + +use nix::sys::stat::Mode; +use proxmox_sys::fs::CreateOptions; + +use crate::namespaced_cache::{ + CacheError, NamespacedCache, ReadableCacheNamespace, WritableCacheNamespace, +}; + +static CACHE_INSTANCE: LazyLock = LazyLock::new(|| { + let file_options = proxmox_product_config::default_create_options(); + let dir_options = file_options.perm(Mode::from_bits_truncate(0o750)); + + PdmCache::new( + // FIXME: `/cache` seems slightly redundant, come up with something else... + PathBuf::from(concat!(pdm_buildcfg::PDM_CACHE_DIR_M!(), "/cache")), + dir_options, + file_options, + ) +}); + +/// Return a handle to the global [`PdmCache`] instance. +pub fn instance() -> &'static PdmCache { + &CACHE_INSTANCE +} + +/// Cache for storing the results of API requests, as well as aggregations thereof. +pub struct PdmCache(NamespacedCache); + +impl PdmCache { + /// Create a new cache instance. + /// + /// # Note + /// Most likely, you want to access the single global instance via [`pdm_cache::instance()`] + /// instead of calling `new` yourself. + fn new>( + base_path: P, + dir_options: CreateOptions, + file_options: CreateOptions, + ) -> Self { + Self(NamespacedCache::new(base_path, dir_options, file_options)) + } + + /// Lock the cache for reading remote-specific data. + pub fn read_remote(&self, remote: &str) -> Result { + let namespace = format!("remote-{remote}"); + self.0.read(&namespace, Duration::from_secs(10)) + } + + /// Lock the cache for writing remote-specific data. + pub fn write_remote(&self, remote: &str) -> Result { + let namespace = format!("remote-{remote}"); + self.0.write(&namespace, Duration::from_secs(10)) + } + + /// Lock the cache for reading global data. + pub fn read_global(&self) -> Result { + self.0.read("global", Duration::from_secs(10)) + } + + /// Lock the cache for writing global data. + pub fn write_global(&self) -> Result { + self.0.write("global", Duration::from_secs(10)) + } +} -- 2.47.3