use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SqliteReplicatorConfig {
pub db_path: PathBuf,
pub s3_bucket: String,
pub s3_prefix: String,
pub cache_dir: PathBuf,
#[serde(default = "default_max_cache_size")]
pub max_cache_size: u64,
#[serde(default = "default_auto_restore")]
pub auto_restore: bool,
#[serde(default = "default_snapshot_interval")]
pub snapshot_interval_secs: u64,
}
fn default_max_cache_size() -> u64 {
100 * 1024 * 1024 }
fn default_auto_restore() -> bool {
true
}
fn default_snapshot_interval() -> u64 {
3600 }
impl Default for SqliteReplicatorConfig {
fn default() -> Self {
Self {
db_path: PathBuf::new(),
s3_bucket: String::new(),
s3_prefix: "sqlite-replication/".to_string(),
cache_dir: PathBuf::from("/tmp/zlayer-replicator/cache"),
max_cache_size: default_max_cache_size(),
auto_restore: default_auto_restore(),
snapshot_interval_secs: default_snapshot_interval(),
}
}
}
impl SqliteReplicatorConfig {
pub fn new(
db_path: impl Into<PathBuf>,
s3_bucket: impl Into<String>,
s3_prefix: impl Into<String>,
) -> Self {
Self {
db_path: db_path.into(),
s3_bucket: s3_bucket.into(),
s3_prefix: s3_prefix.into(),
..Default::default()
}
}
#[must_use]
pub fn with_cache_dir(mut self, cache_dir: impl Into<PathBuf>) -> Self {
self.cache_dir = cache_dir.into();
self
}
#[must_use]
pub fn with_max_cache_size(mut self, size: u64) -> Self {
self.max_cache_size = size;
self
}
#[must_use]
pub fn with_auto_restore(mut self, auto_restore: bool) -> Self {
self.auto_restore = auto_restore;
self
}
#[must_use]
pub fn with_snapshot_interval(mut self, interval_secs: u64) -> Self {
self.snapshot_interval_secs = interval_secs;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LayerStorageConfig {
pub bucket: String,
#[serde(default = "default_prefix")]
pub prefix: String,
pub region: Option<String>,
pub endpoint_url: Option<String>,
pub staging_dir: PathBuf,
pub state_db_path: PathBuf,
#[serde(default = "default_part_size")]
pub part_size_bytes: u64,
#[serde(default = "default_concurrent_uploads")]
pub max_concurrent_uploads: usize,
#[serde(default = "default_compression_level")]
pub compression_level: i32,
#[serde(default = "default_sync_interval")]
pub sync_interval_secs: u64,
}
fn default_prefix() -> String {
"layers/".to_string()
}
fn default_part_size() -> u64 {
64 * 1024 * 1024 }
fn default_concurrent_uploads() -> usize {
4
}
fn default_compression_level() -> i32 {
3
}
fn default_sync_interval() -> u64 {
30
}
impl Default for LayerStorageConfig {
fn default() -> Self {
Self {
bucket: String::new(),
prefix: default_prefix(),
region: None,
endpoint_url: None,
staging_dir: PathBuf::from("/tmp/zlayer-storage/staging"),
state_db_path: zlayer_paths::ZLayerDirs::system_default()
.data_dir()
.join("layer-state.sqlite"),
part_size_bytes: default_part_size(),
max_concurrent_uploads: default_concurrent_uploads(),
compression_level: default_compression_level(),
sync_interval_secs: default_sync_interval(),
}
}
}
impl LayerStorageConfig {
pub fn new(bucket: impl Into<String>) -> Self {
Self {
bucket: bucket.into(),
..Default::default()
}
}
#[must_use]
pub fn with_prefix(mut self, prefix: impl Into<String>) -> Self {
self.prefix = prefix.into();
self
}
#[must_use]
pub fn with_region(mut self, region: impl Into<String>) -> Self {
self.region = Some(region.into());
self
}
#[must_use]
pub fn with_endpoint_url(mut self, url: impl Into<String>) -> Self {
self.endpoint_url = Some(url.into());
self
}
#[must_use]
pub fn with_staging_dir(mut self, path: impl Into<PathBuf>) -> Self {
self.staging_dir = path.into();
self
}
#[must_use]
pub fn with_state_db_path(mut self, path: impl Into<PathBuf>) -> Self {
self.state_db_path = path.into();
self
}
#[must_use]
pub fn object_key(&self, digest: &str) -> String {
format!("{}{}.tar.zst", self.prefix, digest)
}
#[must_use]
pub fn metadata_key(&self, digest: &str) -> String {
format!("{}{}.meta.json", self.prefix, digest)
}
}