Глобально уникальные ID (docs/changes/016): - у устройств, групп, задач, резервных копий и записей журнала ID вида <префикс>_<uuid7> (dev_, grp_, job_, bkp_, evt_): типы не пересекаются, внутри типа ID не повторяются и сортируются по времени; - миграция БД v1 заменяет числовые ID с пересчётом ссылок (копия файла БД перед миграцией, сверка числа строк, одна транзакция); - резервная копия = пара файлов с одним bkp_ ID, файлы в S3 получают метаданные backup-id/device-id; синхронизация метаданных с бакетом; - журнал событий в БД (events): создание/изменение/удаление, задачи, бэкапы, смена online/offline, вход в UI; API чтения GET /api/v1/events. Журнал в UI, ротация и очистка (docs/changes/017): - страница «Журнал»: фильтры, подгрузка «Показать ещё», окно записи; - настройки ротации (срок и максимум записей) хранятся в БД (схема v2), ротация при старте, раз в час и после сохранения настроек; - очистка журнала только через окно с паролем пользователя, блокировка после 5 неверных попыток, остаётся запись о факте очистки; через API очистки нет. Тесты: 20 из 20. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6.1 KiB
6.1 KiB
Итоги: 016 — глобально уникальные ID и журнал событий
Сделано
- ID (
app/ids.py): у каждой сущности —<префикс>_<uuid7>:dev_устройство,grp_группа,job_задача,bkp_резервная копия,evt_запись журнала. Типы не пересекаются по построению (префикс); внутри типа UUIDv7 = время (мс) + 12-битный счётчик + 62 случайных бита, строго возрастает внутри процесса, сортировка по ID = по времени создания; ID не переиспользуются (в отличие от прежнихmax(id)+1); PRIMARY KEY в каждой таблице; ID чужого типа в пути/запросе → 404 с пояснением, числовые ID больше не существуют. - Журнал событий (
events,app/services/events.py): каждая запись со своимevt_ID, ссылкой на ID сущности, актором (ui:<пользователь>/api/poller/system) и данными. Типы:device.created|updated|deleted|online|offline,group.created|renamed|deleted,devices.moved,job.created|started|done|failed,backup.created|done|failed|imported|deleted,auth.login|failed,system.migrated. Вonline/offlineпишутся только смены состояния; пароли в журнал не попадают. API:GET /api/v1/events(фильтрыentity_id,type,device_id,job_id,before,limit),GET /api/v1/events/{id}. UI-страницы журнала нет (нужен макет). - Резервные копии: одна копия = пара файлов с одним
bkp_ID; строка хранитjob_idзадачи и снимок имени устройства; файлы загружаются в S3 с метаданнымиbackup-idиdevice-id; файлы бакета без строки получают ID автоматически (при старте и при просмотре списка), копии без файлов помечаются удалёнными (deleted_at), строка и ID остаются в истории. В API списка файлов естьbackup_id, в UI ID виден в подсказке. - Миграция (
app/migrations.py,PRAGMA user_version0→1): числовые ID заменены везде с пересчётом ссылок, порядок записей сохранён (время в ID берётся изcreated_at), выполняется одной транзакцией, сверяет число строк, перед этим создаёт копию БД (ros_control.db.bak-<метка>в томе). - API/UI: все ID — строки; в таблице «Задачи» колонка «ID» показывает последние 8 символов (полный — в подсказке) — единственное видимое отличие от утверждённого макета.
Проверено
pytest: 17 из 17 (12 прежних обновлены, 5 новых: уникальность 50 тыс. ID и типы, миграция из старой схемы, журнал событий, API журнала и валидация ID, связь бэкапов с бакетом).- Репетиция на копии боевой БД, затем боевая миграция: 4 группы, 6 устройств, 32 задачи, 23 бэкапа — число строк, связи «устройство → группа → задачи → бэкапы» и порядок сохранены; 70 ID, все уникальны; повторный запуск ничего не меняет.
- Сверка с бакетом: 4 копии (08:26–09:38), чьих файлов уже нет в бакете, помечены удалёнными; все 24 файла в бакете связаны с 12 активными копиями.
- Живой журнал: создание тестового устройства (актор
api), уход в offline (акторpoller), удаление; числовой ID и ID чужого типа → 404. Полный сценарий в браузере на мигрированных данных без ошибок JS. - S3: объект загружается с метаданными, значения совпадают. Yandex Object Storage возвращает ключи в виде
Backup-Id,Device-Id— при чтении сравнивать без учёта регистра. Тестовый объект удалён.
Оговорки
- Ломающее изменение: старые curl-скрипты с числовыми ID не работают. Откат — из
ros_control.db.bak-*в томе и предыдущего коммита. - Уже лежащие в бакете объекты метаданных S3 не получили (переписывать объекты не стали): связь с ними — через БД.
- Полный бэкап на реальном устройстве после изменения не запускался (создаёт файлы,
.rscс секретами) — метаданные S3 проверены отдельным тестовым объектом; первый штатный бэкап проверит их на реальных файлах. - Журнал не ротируется (растёт только при изменениях, опрос пишет лишь смены состояния); срок хранения/очистка — при необходимости отдельной доработкой.
- Пробные записи проверки (создание/удаление тестового устройства и группы) остались в журнале как обычные события.