feat: complete TASK-WP0-05 storage capacity
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
export const WARNING_LIMIT_BYTES = 4_294_967_296;
|
||||
export const CRITICAL_LIMIT_BYTES = 4_831_838_208;
|
||||
export const HARD_LIMIT_BYTES = 5_368_709_120;
|
||||
export const CAPACITY_COUNTED_FILE_KINDS = [
|
||||
"reference",
|
||||
"generated",
|
||||
"export",
|
||||
"derived",
|
||||
"sticker_original",
|
||||
"sticker_thumbnail",
|
||||
] as const;
|
||||
export const CAPACITY_EXCLUDED_STORAGE = [
|
||||
"read_only_assets",
|
||||
"application_files",
|
||||
"database",
|
||||
"logs",
|
||||
"audit",
|
||||
"browser_cache",
|
||||
"user_downloads",
|
||||
] as const;
|
||||
|
||||
export type CapacityNoticeLevel = "normal" | "warning" | "critical";
|
||||
export type StorageStatus = "active" | "full" | "unavailable";
|
||||
export type StorageAction =
|
||||
| "project_json_write"
|
||||
| "binary_write"
|
||||
| "ai_call"
|
||||
| "latest_export_write"
|
||||
| "read"
|
||||
| "download"
|
||||
| "client_only_download"
|
||||
| "permanent_delete"
|
||||
| "explicit_cleanup";
|
||||
export type StorageActionDecision = "allow" | "reject_capacity" | "reject_unavailable" | "reject_uncommitted";
|
||||
|
||||
export function classifyCapacity(managedContentBytes: number, activeReservationBytes: number) {
|
||||
if (!Number.isSafeInteger(managedContentBytes) || managedContentBytes < 0) throw new Error("managed_content_bytes_invalid");
|
||||
if (!Number.isSafeInteger(activeReservationBytes) || activeReservationBytes < 0) throw new Error("active_reservation_bytes_invalid");
|
||||
const capacity_notice_level: CapacityNoticeLevel = managedContentBytes < WARNING_LIMIT_BYTES
|
||||
? "normal"
|
||||
: managedContentBytes < CRITICAL_LIMIT_BYTES
|
||||
? "warning"
|
||||
: "critical";
|
||||
const storage_status: StorageStatus = managedContentBytes + activeReservationBytes >= HARD_LIMIT_BYTES
|
||||
? "full"
|
||||
: "active";
|
||||
return { capacity_notice_level, storage_status };
|
||||
}
|
||||
|
||||
export function decideStorageAction(
|
||||
status: StorageStatus,
|
||||
sqliteWritable: boolean,
|
||||
action: StorageAction,
|
||||
): StorageActionDecision {
|
||||
if (status === "unavailable") {
|
||||
if (action === "read" || action === "download" || action === "client_only_download") return "allow";
|
||||
if (action === "permanent_delete" || action === "explicit_cleanup") {
|
||||
return sqliteWritable ? "allow" : "reject_uncommitted";
|
||||
}
|
||||
return "reject_unavailable";
|
||||
}
|
||||
if (status === "full" && (action === "binary_write" || action === "ai_call" || action === "latest_export_write")) {
|
||||
return "reject_capacity";
|
||||
}
|
||||
return "allow";
|
||||
}
|
||||
|
||||
export function storageCapacityErrorDetails(input: {
|
||||
activeReservationBytes: number;
|
||||
managedContentBytes: number;
|
||||
projectedWriteBytes: number;
|
||||
}) {
|
||||
const { capacity_notice_level, storage_status } = classifyCapacity(
|
||||
input.managedContentBytes,
|
||||
input.activeReservationBytes,
|
||||
);
|
||||
return {
|
||||
capacity_status: storage_status === "full" ? "full" as const : capacity_notice_level,
|
||||
remaining_bytes: Math.max(0, HARD_LIMIT_BYTES - input.managedContentBytes - input.activeReservationBytes),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user