feat(drive): add quota calculus per drive
- quota per drive
- add 2 internal API endpoints to test purpose
disabled by default, enable it via `OXICLOUD_ENABLE_ADMIN_INTERNAL_ENDPOINTS=true`
this enable:
/api/admin/internal/trigger-sweep
to sweep the trash and recalculated quota
/api/admin/internal/trigger-gc
to garbage orphan blobs
use full for end to end tests and validate lifecycles
This commit is contained in:
@@ -214,7 +214,7 @@ impl ChunkedUploadHandler {
|
||||
.await
|
||||
{
|
||||
tracing::warn!(
|
||||
"⛔ CHUNKED UPLOAD REJECTED (quota): user={}, file={}, size={} — {}",
|
||||
"⛔ CHUNKED UPLOAD REJECTED (user quota): user={}, file={}, size={} — {}",
|
||||
auth_user.username,
|
||||
request.filename,
|
||||
request.total_size,
|
||||
@@ -230,6 +230,37 @@ impl ChunkedUploadHandler {
|
||||
.into_response();
|
||||
}
|
||||
|
||||
// ── Per-drive quota (D4) ─────────────────────────────────
|
||||
// Native-chunked declares `total_size` at session creation,
|
||||
// so we can refuse here before any chunk is accepted — same
|
||||
// wasted-bandwidth optimisation the multipart path has via
|
||||
// the post-ingest check. No folder_id means root-level which
|
||||
// the folder-permission check above already rejects.
|
||||
if let Some(storage_svc) = state.storage_usage_service.as_ref()
|
||||
&& let Some(fid_str) = request.folder_id.as_deref()
|
||||
&& let Ok(fid) = uuid::Uuid::parse_str(fid_str)
|
||||
&& let Err(err) = storage_svc
|
||||
.check_drive_quota_by_folder(fid, request.total_size)
|
||||
.await
|
||||
{
|
||||
tracing::warn!(
|
||||
"⛔ CHUNKED UPLOAD REJECTED (drive quota): user={}, folder={}, file={}, size={} — {}",
|
||||
auth_user.username,
|
||||
fid,
|
||||
request.filename,
|
||||
request.total_size,
|
||||
err.message
|
||||
);
|
||||
return (
|
||||
StatusCode::INSUFFICIENT_STORAGE,
|
||||
Json(serde_json::json!({
|
||||
"error": err.message,
|
||||
"error_type": "QuotaExceeded"
|
||||
})),
|
||||
)
|
||||
.into_response();
|
||||
}
|
||||
|
||||
// Validate chunk size if provided
|
||||
let chunk_size = request.chunk_size.unwrap_or(DEFAULT_CHUNK_SIZE);
|
||||
if chunk_size < 1024 * 1024 {
|
||||
|
||||
Reference in New Issue
Block a user