feat(quota): per-group total-byte quotas for shared KV + docs (Track A M4)
M3 quotas capped a group's shared KV/docs by ROW count only; a group could still
blow past storage with few-but-huge values. Add the symmetric total-bytes ceiling
(files already had one).
- group_quota: PICLOUD_GROUP_{KV,DOCS}_MAX_TOTAL_BYTES env vars (default 256 MiB)
+ accessors.
- GroupKvRepo/GroupDocsRepo: total_bytes(group) = SUM(octet_length(value::text))
(default Ok(0) so non-Postgres impls skip the check).
- GroupKv/DocsServiceImpl: check the PROJECTED total (old value's bytes
subtracted, new added) on every set/create/update, so a same-or-smaller update
near the cap is still allowed (unlike a naive used+new check). New
TotalBytesQuotaExceeded errors; +with_max_total_bytes for tests.
- KV set switched has->get to obtain the old value's size for the delta.
Pinned by group_kv_service + group_docs_service per_group_byte_quota_uses_the_
projected_total unit tests (reject over-cap, allow same/smaller update near cap).
No migration. CLAUDE.md env-var table updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -181,6 +181,11 @@ pub enum GroupDocsError {
|
||||
#[error("group docs: quota exceeded ({actual} rows; limit {limit})")]
|
||||
QuotaExceeded { limit: usize, actual: usize },
|
||||
|
||||
/// The owning group's shared-docs store would exceed its total-bytes quota
|
||||
/// (`PICLOUD_GROUP_DOCS_MAX_TOTAL_BYTES`). `actual` is the projected total.
|
||||
#[error("group docs: total-bytes quota exceeded ({actual} bytes; limit {limit})")]
|
||||
TotalBytesQuotaExceeded { limit: u64, actual: u64 },
|
||||
|
||||
#[error("group docs backend error: {0}")]
|
||||
Backend(String),
|
||||
}
|
||||
|
||||
@@ -141,6 +141,12 @@ pub enum GroupKvError {
|
||||
#[error("group kv: quota exceeded ({actual} rows; limit {limit})")]
|
||||
QuotaExceeded { limit: usize, actual: usize },
|
||||
|
||||
/// The owning group's shared-KV store would exceed its total-bytes quota
|
||||
/// (`PICLOUD_GROUP_KV_MAX_TOTAL_BYTES`). `actual` is the projected total
|
||||
/// (old value's bytes subtracted, new value's added).
|
||||
#[error("group kv: total-bytes quota exceeded ({actual} bytes; limit {limit})")]
|
||||
TotalBytesQuotaExceeded { limit: u64, actual: u64 },
|
||||
|
||||
/// Anything else — Postgres unavailable, serialization failure, etc.
|
||||
#[error("group kv backend error: {0}")]
|
||||
Backend(String),
|
||||
|
||||
Reference in New Issue
Block a user