From e67533ec804763d3d65d6c13ecf7ba4974d07571 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Sun, 1 Nov 2026 21:17:13 +0700 Subject: [PATCH 1/2] feat(server): register garbage collector configuration --- objectstore-server/src/config.rs | 28 +++++++++++++++++++ .../src/garbage_collector/mod.rs | 20 +++++++++++++ 2 files changed, 48 insertions(+) diff --git a/objectstore-server/src/config.rs b/objectstore-server/src/config.rs index 040dc275..693eebca 100644 --- a/objectstore-server/src/config.rs +++ b/objectstore-server/src/config.rs @@ -68,6 +68,7 @@ use objectstore_service::backend::local_fs::FileSystemConfig; #[cfg(feature = "storage-cogs")] use objectstore_service::change_stream::CostTrackerConfig; use objectstore_service::encryption::Cipher; +use objectstore_service::garbage_collector::GarbageCollectorConfig; use objectstore_types::auth::Permission; use secrecy::{CloneableSecret, SecretBox, SerializableSecret, zeroize::Zeroize}; use serde::{Deserialize, Serialize}; @@ -550,6 +551,32 @@ pub struct Config { #[serde(default)] pub storage_cogs: Option, + /// Garbage collector configuration. + /// + /// Selects the backend of the garbage collector's expiration index, which records, per + /// object, the deadline at which that object becomes eligible for deletion. The index is + /// kept in sync on the write path and read back by the collector to find expired objects, + /// so it must be configured with the same lifetime as the storage backend: an index that + /// is lost or reset leaves objects behind with nothing scheduling their deletion. + /// + /// `None` is the default: no expiration index is configured. + /// + /// # Environment Variables + /// + /// - `OS__GARBAGE_COLLECTOR__TYPE=sqlite` + /// - `OS__GARBAGE_COLLECTOR__PATH=/data/objectstore.db` + /// + /// # Example + /// + /// ```yaml + /// garbage_collector: + /// type: sqlite + /// path: /data/objectstore.db + /// ``` + /// + /// See [`GarbageCollectorConfig`] for the available backends and their fields. + pub garbage_collector: Option, + /// Configuration of the internal task runtime. /// /// Controls the thread pool size and behavior of the async runtime powering the server. @@ -858,6 +885,7 @@ impl Default for Config { #[cfg(feature = "storage-cogs")] storage_cogs: None, + garbage_collector: None, runtime: Runtime::default(), logging: LoggingConfig::default(), sentry: Sentry::default(), diff --git a/objectstore-service/src/garbage_collector/mod.rs b/objectstore-service/src/garbage_collector/mod.rs index 5e28034b..656414a0 100644 --- a/objectstore-service/src/garbage_collector/mod.rs +++ b/objectstore-service/src/garbage_collector/mod.rs @@ -11,8 +11,10 @@ pub mod sqlite; use std::fmt::Debug; use objectstore_types::time::Timestamp; +use serde::{Deserialize, Serialize}; use crate::change_stream::ChangeStreamError; +use crate::garbage_collector::sqlite::SqliteGarbageCollectorConfig; use crate::id::ObjectId; /// Stores object expiration metadata for the garbage collector. @@ -49,3 +51,21 @@ pub trait GcStorage: Send + Sync + Debug { limit: u64, ) -> Result, ChangeStreamError>; } + +/// Backend selection for the garbage collector's expiration index. +/// +/// Each variant wraps that backend's own configuration and corresponds to a [`GcStorage`] +/// implementation. The enum is internally tagged: in YAML the variant is named by a `type` +/// key, and through environment variables by the `OS__GARBAGE_COLLECTOR__TYPE` prefix plus +/// the variant's fields (e.g. `OS__GARBAGE_COLLECTOR__TYPE=sqlite`). +/// +/// ```yaml +/// garbage_collector: +/// type: sqlite +/// path: /data/objectstore.db +/// ``` +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +pub enum GarbageCollectorConfig { + Sqlite(SqliteGarbageCollectorConfig), +} From 7bb9d797a0066029e2014812f1479da13fba1825 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Sun, 1 Nov 2026 21:25:46 +0700 Subject: [PATCH 2/2] docs: missing enum --- objectstore-service/src/garbage_collector/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/objectstore-service/src/garbage_collector/mod.rs b/objectstore-service/src/garbage_collector/mod.rs index 656414a0..8b9da011 100644 --- a/objectstore-service/src/garbage_collector/mod.rs +++ b/objectstore-service/src/garbage_collector/mod.rs @@ -67,5 +67,11 @@ pub trait GcStorage: Send + Sync + Debug { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "lowercase")] pub enum GarbageCollectorConfig { + /// SQLite-backed index, serialized as `type: sqlite`. + /// + /// Stores one row per object in a local SQLite database, see + /// [`SqliteGarbageCollectorConfig`] for its fields. The database file must live on + /// storage that survives restarts and is shared by every server that writes objects, + /// otherwise the index diverges from the objects actually stored. Sqlite(SqliteGarbageCollectorConfig), }