From 69f04dec87214505f08985d7c5b6f2b049c1cbd0 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 6 Oct 2026 00:29:28 +0200 Subject: [PATCH] Document per-user quotas and the client quota query --- doc/member_files.txt | 45 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/doc/member_files.txt b/doc/member_files.txt index 622f1d7c..8001a6e1 100644 --- a/doc/member_files.txt +++ b/doc/member_files.txt @@ -12,20 +12,34 @@ Корень по умолчанию: /member_files/ (без db_path — ./member_files/). Публичное дерево: <корень>///<относительный путь>. Временные файлы: <корень>/.uploads/. -Корень создаётся лениво по первому разрешённому файловому запросу. +При старте сервис создаёт/открывает корень в дисковом worker, удаляет старые +незавершённые temp и сканирует опубликованные файлы. До готовности отвечает BUSY. +Ошибка сканирования оставляет локальное хранилище недоступным до restart; +частичные счётчики клиенту не выдаются. Клиентские передачи к другим серверам продолжают работать. Очистка кэша вложений media/ это дерево не обходит. Настройки [chatserver] / [chat]: member_files_enabled=1 - member_files_quota_mb=1024 + member_files_user_quota_mb=1024 member_files_upload_ttl_sec=3600 member_files_path=/путь/к/хранилищу (опционально, до 255 байт UTF-8) Путь, квота и TTL читаются при старте чат-сервиса; изменение требует его restart. -enabled проверяется на каждом запросе. Квота общая для дерева всех групп, -включает опубликованные файлы и полный конечный размер временных загрузок. -Замена требует места одновременно для прежнего файла и нового. +enabled проверяется на каждом запросе. Лимит одинаков для каждого UID отдельно, +размер UID суммируется по всем группам на этом сервере. Значение в МиБ (1024*1024 байт). +Счётчики used/reserved хранятся в памяти дискового worker и восстанавливаются с диска. +Каталоги не учитываются. Сохранённые файлы удалённых участников также занимают квоту. +При начале загрузки резервируется размер нового файла или положительный прирост при замене. +WRITE не изменяет used; COMMIT обновляет used на разницу размеров и освобождает резерв. +ABORT/Cancel/TTL освобождают резерв после удаления temp; REMOVE вычитает размер файла. +Переименование внутри UID и операции с каталогами не меняют размер. +Повторы BEGIN/COMMIT/REMOVE не меняют учёт повторно. +Уже превышенная квота не удаляет данные: чтение, удаление и уменьшение файла доступны, +новый положительный прирост запрещён. Физический temp может занимать больше места, +чем резерв прироста; нехватка места файловой системы остаётся отдельной I/O-ошибкой. Нехватка квоты/места возвращает NO_SPACE; опубликованные файлы не вытесняются. +Общая member_files_quota_mb удалена. Корень обслуживается только файловым сервисом; +ручные изменения требуют повторного сканирования через restart. Сервер — действующий полный мембер группы с подписанным adm_tags.storage="yes". Колонка peers.storage — производный сетевой приоритет, для полномочий не используется. @@ -37,11 +51,11 @@ src == owner. Удалённые записи и source=1 (плейсхолде Открытый fd/UUID загрузки не отменяют повторную проверку членства. Файлы удалённого участника сохраняются на диске, но через сервис не доступны. -Wire, версия 2 +Wire, версия 3 -------------- Все числа LE, без сырых структур и padding. Фиксированный заголовок 125 байт: - 0 protocol_version:u8 = 2 + 0 protocol_version:u8 = 3 1 kind:u8 (1=request, 2=response) 2 command:u8 3 status:u16 (request=0) @@ -130,6 +144,12 @@ Windows удерживает родительские каталоги без SH Ошибка сервера приходит END.status!=OK; ошибка открытия — ответом на STREAM_READ/WRITE. 15 STREAM_CANCEL: клиент отменяет конкретный поток. Поздние DATA не публикуются. +16 QUOTA: owner=UID, path/target пустые, cursor=0, data_len=0. + Права чтения те же, что у STAT/LIST выбранного участника. Ответ data_len=24: + used:u64, limit:u64, reserved:u64, LE, в байтах. Размер общий для UID во всех группах. + Не резервирует место и не занимает квитанцию мутации. used может превышать limit + после уменьшения лимита; сервер не выдаёт фиктивный нулевой размер при ошибке учёта. + Открытие потока — обычный повторяемый запрос с отдельным request_id. cursor связывает его с DATA/END/CANCEL. Поток определяется group/peer/kind/ID; один ID не может одновременно обозначать разные открытия. Каждый пакет по-прежнему подписан и зашифрован. @@ -204,6 +224,11 @@ Upload/Download/New folder/Rename/Delete, прогресс и Cancel transfer. Чужой UID доступен только для чтения. Автор может быть offline. Open скачивает в выбранный пользователем локальный файл и открывает его приложением ОС после завершения. Смена контекста отбрасывает поздние ответы. +Для выбранного UID строка хранилища показывает занято/всего и резерв текущих загрузок. +Точные байты доступны в tooltip. QUOTA запрашивается отдельно от LIST при выборе +сервера/UID, обновлении каталога, завершении передачи и каждые две секунды видимого окна. +Поздние ответы старого UID/сервера игнорируются. BUSY при стартовом сканировании +сохраняет Loading directory и повторяет LIST через секунду; новый переход отменяет повтор. API параллельных передач ----------------------- @@ -230,13 +255,15 @@ Stop сервиса/группы завершает все принадлежа --------------------- tests/test_member_files: wire/UTF-8, произвольные блоки, повторы, EOF, версии, -короткая замена, SHA256, пустой файл, квота, ссылки, expiry/restart, 10-секундный +короткая замена, SHA256, пустой файл, независимые квоты UID, общий учёт по группам, +резервирование/повторы/TTL, стартовый scan и его ошибки, ссылки, expiry/restart, 10-секундный fd idle и принадлежность work/done потокам. tests/test_member_files_network: настоящие A/B/M, подписанная storage-роль, параллельные upload/download одного пира, local loopback, пустые файлы, побайтная проверка, отмена одного handle, restart router и destroy с активным server I/O. Шестисекундная задержка worker проверяет receive backpressure и busy ACK. Также проверяются чужая запись, виртуальный корень и подписанное удаление читателя. +QUOTA проверяется на настоящем подписанном/зашифрованном канале; удалённый читатель не получает счётчики. test_services — stop/start общего чат-сервиса. Текущая диагностика выделена в категорию debug. Настройка для полного трасса: [debug] @@ -247,6 +274,8 @@ read/write и передачу задач/завершений между дис stream progress раз в секунду показывает ID/направление, done/total, число блоков в кольце, активность I/O, причину ожидания и скорость B/s. Router логирует переходы receive paused/resumed и peer receive busy без повторного сообщения на каждый блок. +quota scan started/ready показывают путь, число пользователей и время обхода; +quota updated показывает UID/операцию/used/reserved; quota exceeded — used/reserved/growth/limit. По request_id видны GUI post → core request → router seq → server rx → ACL → disk queued/start/done → response tx → GUI result/bridge → directory ready. PID создания worker, PID отправки задачи и startup PID позволяют однозначно