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
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# Spec Delta
|
||||
|
||||
## Purpose
|
||||
|
||||
Выбор и работа слоя метаданных: внешняя PostgreSQL или встроенная SQLite, с
|
||||
паритетным поведением для одного экземпляра приложения.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Выбор бэкенда метаданных
|
||||
Система SHALL поддерживать выбор бэкенда слоя метаданных параметром конфигурации,
|
||||
при этом PostgreSQL SHALL оставаться значением по умолчанию.
|
||||
|
||||
#### Scenario: Выбор PostgreSQL
|
||||
- **WHEN** в конфигурации задан бэкенд PostgreSQL
|
||||
- **THEN** метаданные читаются и пишутся во внешнюю PostgreSQL
|
||||
|
||||
#### Scenario: Выбор встроенной SQLite
|
||||
- **WHEN** в конфигурации задан бэкенд SQLite
|
||||
- **THEN** метаданные читаются и пишутся в локальный файл SQLite без внешней службы
|
||||
|
||||
#### Scenario: Неполная конфигурация
|
||||
- **WHEN** конфигурация выбранного бэкенда неполна
|
||||
- **THEN** система отказывается стартовать с явной ошибкой конфигурации
|
||||
|
||||
### Requirement: Паритет поведения бэкендов
|
||||
Оба бэкенда метаданных SHALL обеспечивать одинаковое наблюдаемое поведение системы:
|
||||
аутентификацию, альбомы, роли и доступ, фото, объектный журнал, сборку мусора и
|
||||
очередь генерации вариантов.
|
||||
|
||||
#### Scenario: Одинаковое поведение API
|
||||
- **WHEN** один и тот же сценарий выполняется на PostgreSQL и на SQLite
|
||||
- **THEN** наблюдаемые результаты и ошибки API совпадают
|
||||
|
||||
#### Scenario: Соблюдение прав доступа
|
||||
- **WHEN** на любом бэкенде участник без прав выполняет запрещённое действие
|
||||
- **THEN** система отклоняет действие одинаковым образом
|
||||
|
||||
### Requirement: Встроенный одиночный экземпляр
|
||||
Бэкенд SQLite SHALL работать как самодостаточный режим для одного экземпляра приложения,
|
||||
и система SHALL отвергать или явно документировать использование одного файла SQLite
|
||||
несколькими экземплярами.
|
||||
|
||||
#### Scenario: Один экземпляр
|
||||
- **WHEN** приложение запущено в единственном экземпляре
|
||||
- **THEN** SQLite корректно обслуживает всех пользователей этого экземпляра
|
||||
|
||||
#### Scenario: Совместная работа с файлом
|
||||
- **WHEN** предполагается совместная работа нескольких экземпляров с одним файлом SQLite
|
||||
- **THEN** конфигурация считает такой режим неподдерживаемым
|
||||
|
||||
### Requirement: Атомарность жизненного цикла объектов
|
||||
На обоих бэкендах привязка готового объекта к фото и заявка объекта на удаление SHALL
|
||||
быть атомарными и SHALL исключать привязку объекта, который собирается быть удалён, и
|
||||
удаление используемого объекта.
|
||||
|
||||
#### Scenario: Конкурентная привязка и сборка мусора
|
||||
- **WHEN** привязка объекта и заявка на его удаление происходят одновременно
|
||||
- **THEN** система либо привязывает объект без удаления, либо удаляет его без привязки
|
||||
|
||||
#### Scenario: Повторная привязка
|
||||
- **WHEN** объект уже привязан к фото в роли
|
||||
- **THEN** повторная привязка приводит к согласованному состоянию без дублей
|
||||
|
||||
### Requirement: Устойчивость к перезапуску
|
||||
Очередь генерации вариантов и сборка мусора SHALL восстанавливаться из состояния слоя
|
||||
метаданных после перезапуска на обоих бэкендах, и система SHALL применять схему
|
||||
метаданных при старте.
|
||||
|
||||
#### Scenario: Незавершённые задания
|
||||
- **WHEN** процесс перезапускается с незавершёнными заданиями генерации вариантов
|
||||
- **THEN** обработка заданий продолжается
|
||||
|
||||
#### Scenario: Применение схемы
|
||||
- **WHEN** приложение стартует с выбранным бэкендом
|
||||
- **THEN** схема метаданных выбранного бэкенда приведена к актуальному состоянию
|
||||
Reference in New Issue
Block a user