Files
ds-galo/openspec/changes/storage-orphan-reconciliation/specs/storage-reconciliation/spec.md
T
iu 176a8d8ced feat(metadata): SQLite backend, storage reconciliation and local defaults
- pluggable per-domain Repository interfaces; PostgreSQL and SQLite impls
- SQLite on modernc.org/sqlite (WAL, busy_timeout, foreign_keys, immediate tx)
- separate migrations/sqlite and db.MigrateSQLite; store.NewPostgres/NewSQLite
- cmd/reconcile compares object storage with the journal (report, then --delete)
- storage.Backend.List and photos.Repository.AllStorageKeys
- DB_BACKEND/SQLITE_PATH and STORAGE_BACKEND/FS_ROOT selectable; local defaults
  (sqlite ./galo.db, fs ./data)
- Makefile reconcile/reconcile-delete; docs and .env.example updated
2026-10-11 10:08:31 +03:00

4.4 KiB

Spec Delta

Purpose

Ручная сверка объектного хранилища с журналом метаданных: инвентаризация обеих сторон, отчёт о расхождениях и безопасное удаление осиротевших блобов.

ADDED Requirements

Requirement: Инвентаризация хранилища

Слой хранения SHALL перечислять объекты под заданным префиксом, возвращая ключ, размер и время изменения, независимо от бэкенда (S3-совместимое или локальная ФС).

Scenario: Перечисление в S3-совместимом хранилище

  • WHEN запрашивается список объектов под префиксом
  • THEN возвращаются все ключи с этим префиксом с их размером и временем изменения

Scenario: Перечисление в локальной ФС

  • WHEN хранилищем выбрана локальная ФС
  • THEN возвращаются ключи всех блобов под префиксом с их размером и временем изменения

Requirement: Инвентаризация журнала

Слой метаданных SHALL возвращать все ключи, зарегистрированные в журнале objects, на обоих бэкендах (PostgreSQL и SQLite).

Scenario: Ключи журнала

  • WHEN запрашиваются ключи журнала
  • THEN возвращается множество ключей всех строк objects

Requirement: Отчёт о расхождениях

По умолчанию сверка SHALL выполняться в режиме отчёта и SHALL не изменять хранилище; отчёт SHALL различать сироты (в хранилище есть, в журнале нет) и пропавшие (в журнале есть, в хранилище нет).

Scenario: Только отчёт

  • WHEN сверка запущена без флага удаления
  • THEN система выводит число и примеры сирот и пропавших, ничего не удаляя

Scenario: Пропавшие не восстанавливаются

  • WHEN ключ есть в журнале, но отсутствует в хранилище
  • THEN он сообщается как пропавший и не создаётся и не удаляется

Requirement: Удаление сирот по явному запросу

Удаление сирот SHALL выполняться только по явному флагу, только для ключей под префиксом объектов и только для блобов старше заданного минимального возраста.

Scenario: Удаление включено

  • WHEN сверка запущена с флагом удаления
  • THEN сироты старше минимального возраста удаляются из хранилища, а более молодые пропускаются

Scenario: Защита от гонки с загрузкой

  • WHEN блоб создан недавно (моложе минимального возраста)
  • THEN он не удаляется, даже если строки в журнале ещё нет

Scenario: Ограничение области

  • WHEN удаление включено
  • THEN удаляются только ключи под префиксом объектов, остальные не затрагиваются

Requirement: Независимость от бэкендов

Сверка SHALL работать с любой комбинацией бэкенда хранения (S3 или ФС) и бэкенда метаданных (PostgreSQL или SQLite).

Scenario: Комбинации бэкендов

  • WHEN сверка запускается на выбранной конфигурации
  • THEN она использует выбранные бэкенды хранения и метаданных без изменений кода