feat(uploads): add OXICLOUD_CHUNK_DIR + documentation for admins
explain OXICLOUD_CHUNK_DIR and OXICLOUD_UPLOAD_TMPDIR
and also the OXICLOUD_CHUNK_MAX_BYTES & OXICLOUD_UPLOAD_TMPDIR
to help administratorrs to defined correctly their storage architecture
This commit is contained in:
@@ -224,6 +224,15 @@ pub struct StorageConfig {
|
||||
/// memory limit and can trigger OOMKill on large files). Env:
|
||||
/// `OXICLOUD_UPLOAD_TMPDIR`.
|
||||
pub upload_temp_dir: Option<PathBuf>,
|
||||
/// Root directory for chunked-upload sessions. When `Some`, chunks land
|
||||
/// under `{chunk_dir}/{upload_id}/` (REST) and
|
||||
/// `{chunk_dir}/nextcloud/{user}/{upload_id}/` (NC). When `None`, falls
|
||||
/// back to `{root_dir}/.uploads/`. Pointing this at the **same
|
||||
/// filesystem** as `.blobs/` keeps the final assembled-to-blob promotion
|
||||
/// an atomic `rename(2)` rather than a full cross-FS copy; pointing it
|
||||
/// at fast storage (NVMe) accelerates the chunk-write + assembly loop
|
||||
/// independently of where final blobs live. Env: `OXICLOUD_CHUNK_DIR`.
|
||||
pub chunk_dir: Option<PathBuf>,
|
||||
/// Interval (seconds) of the background sweep that reconciles every user's
|
||||
/// cached `storage_used_bytes` with the real sum of their files. Keeps the
|
||||
/// quota fresh for all mutations without recomputing on the request path.
|
||||
@@ -368,6 +377,7 @@ impl Default for StorageConfig {
|
||||
max_upload_size: MAX_UPLOAD_SIZE,
|
||||
chunk_max_bytes: 100 * 1024 * 1024, // 100 MB — sane upper bound for a single chunked-upload PUT
|
||||
upload_temp_dir: None,
|
||||
chunk_dir: None,
|
||||
usage_reconcile_secs: 600, // 10 minutes
|
||||
backend: StorageBackendType::Local,
|
||||
s3: None,
|
||||
@@ -1245,6 +1255,16 @@ impl AppConfig {
|
||||
{
|
||||
config.storage.upload_temp_dir = Some(PathBuf::from(dir.trim()));
|
||||
}
|
||||
// Chunked-upload session root — separate from the PUT spool because
|
||||
// chunked sessions accumulate disk on long uploads (multi-chunk
|
||||
// resumable transfers) while PUT spool is short-lived. Sysadmins
|
||||
// commonly want one of them on fast/local storage (NVMe) and the
|
||||
// other on bulk storage; this knob lets that be expressed.
|
||||
if let Ok(dir) = env::var("OXICLOUD_CHUNK_DIR")
|
||||
&& !dir.trim().is_empty()
|
||||
{
|
||||
config.storage.chunk_dir = Some(PathBuf::from(dir.trim()));
|
||||
}
|
||||
|
||||
// Background storage-usage reconciliation interval
|
||||
if let Ok(secs) =
|
||||
|
||||
+27
-4
@@ -171,11 +171,23 @@ impl AppServiceFactory {
|
||||
// Initialize thumbnail directories
|
||||
thumbnail_service.initialize().await?;
|
||||
|
||||
// Chunked upload service for large files (>10MB)
|
||||
let chunked_temp_dir = std::path::PathBuf::from(&self.storage_path).join(".uploads");
|
||||
// Chunked upload service for large files (>10MB).
|
||||
// Root for both REST (`/api/uploads/...`) and NC (`/dav/uploads/...`)
|
||||
// chunked sessions: honour `OXICLOUD_CHUNK_DIR` when set so sysadmins
|
||||
// can put session directories on fast storage (NVMe) or on the same
|
||||
// filesystem as `.blobs/` (turns the final blob promotion into an
|
||||
// atomic rename instead of a cross-FS copy). Falls back to
|
||||
// `{storage_path}/.uploads/` when unset — backwards-compatible with
|
||||
// every existing deployment.
|
||||
let chunk_root = self
|
||||
.config
|
||||
.storage
|
||||
.chunk_dir
|
||||
.clone()
|
||||
.unwrap_or_else(|| std::path::PathBuf::from(&self.storage_path).join(".uploads"));
|
||||
let chunked_upload_service = Arc::new(
|
||||
crate::infrastructure::services::chunked_upload_service::ChunkedUploadService::new(
|
||||
chunked_temp_dir,
|
||||
chunk_root.clone(),
|
||||
)
|
||||
.await,
|
||||
);
|
||||
@@ -870,7 +882,18 @@ impl AppServiceFactory {
|
||||
);
|
||||
}
|
||||
|
||||
let chunk_base = self.storage_path.join(".uploads/nextcloud");
|
||||
// NC chunked-upload sessions root. Honour `OXICLOUD_CHUNK_DIR`
|
||||
// (same env var that the REST chunked service uses) so a single
|
||||
// value covers both surfaces and they stay co-located on one
|
||||
// filesystem; fall back to `{storage_path}/.uploads/` to match
|
||||
// the legacy layout.
|
||||
let chunk_root = self
|
||||
.config
|
||||
.storage
|
||||
.chunk_dir
|
||||
.clone()
|
||||
.unwrap_or_else(|| self.storage_path.join(".uploads"));
|
||||
let chunk_base = chunk_root.join("nextcloud");
|
||||
let chunked_uploads = Arc::new(NextcloudChunkedUploadService::new(chunk_base));
|
||||
|
||||
let file_id_repo = Arc::new(
|
||||
|
||||
Reference in New Issue
Block a user