База, хранилище и кэш
База данных, объектное хранилище и кэш
PostgreSQL
Основная база данных - PostgreSQL 16. API использует async SQLAlchemy, а воркеры используют синхронные SQLAlchemy-сессии. Миграции находятся в schemion-api/alembic.
Строка подключения по умолчанию для API:
postgresql+asyncpg://admin:admin@database:5432/schemionСтрока подключения по умолчанию для воркеров:
postgresql://admin:admin@database:5432/schemionОсновные таблицы
users
Пользователи системы.
Поля:
id- UUID primary key;email- уникальный email;hashed_password- хэш пароля;created_at- время создания.
Связи:
tasks;datasets;models;user_roles.
datasets
Метаданные загруженных датасетов.
Поля:
id- UUID primary key;name- имя датасета;minio_path- объектный путь ZIP-архива в MinIO;user_id- владелец датасета;description- описание;created_at- время создания.
Связи:
models;tasks;user.
models
Метаданные моделей.
Поля:
id- UUID primary key;name- имя модели;architecture- тип архитектуры;architecture_profile- профиль архитектуры;classes- массив классов;minio_model_path- путь к весам модели;metrics_path- путь к JSON-метрикам;user_id- владелец модели; для системных моделей может бытьNULL;is_system- системная ли модель;base_model_id- ссылка на базовую модель;dataset_id- датасет, использованный при обучении;created_at- время создания.
Связи:
dataset;tasks;base_model;derived_models;user.
tasks
Асинхронные задачи инференса и обучения.
Поля:
id- UUID primary key;user_id- владелец задачи;task_type-inferenceилиtraining;status-queued,running,succeeded,failed;model_id- связанная модель;dataset_id- связанный датасет;input_path- входной объект MinIO;output_path- выходной объект MinIO;error_msg- текст ошибки;created_at- время создания;updated_at- время последнего обновления.
RBAC-таблицы
В API присутствуют модели:
roles;permissions;user_roles;role_permissions.
JWT включает роли и разрешения пользователя. Middleware административной панели проверяет наличие роли admin.
MinIO
MinIO используется как S3-compatible object storage. В базе данных хранятся только object names, а не сами файлы.
Настройки по умолчанию:
endpoint: minio:9000
public endpoint для ссылок API: localhost:9000
access key: minioadmin
secret key: minioadminБакеты
schemas-images
Входные файлы для инференса. API загружает сюда изображения или PDF из POST /tasks/create/inference.
datasets
ZIP-архивы датасетов, загруженные через POST /datasets/create.
models
Файлы весов моделей:
- системные модели, загруженные через
system_model_importer; - пользовательские модели, загруженные через API;
- fine-tuned модели, созданные training-воркером.
metrics
JSON-файлы метрик обучения.
inference-results
JSON-файлы результатов инференса.
Object naming
API-слой при загрузке файла в MinIO добавляет UUID-префикс:
<uuid>_<filename>Для датасетов и входных файлов перед загрузкой формируется путь вида:
<user_id>/<filename>Но итоговый object name все равно получает UUID-префикс на уровне MinioStorage.upload_file.
system_model_importer сохраняет системные модели в:
system/<uuid>_<model_name>.<ext>Presigned URLs
API не отдает файлы напрямую. Для скачивания используются presigned URLs:
/datasets/download/{dataset_id};/models/download/{model_id};/models/metrics/{model_id};- поле
output_urlвTaskRead.
Для задач срок жизни output_url равен TTL кэша задач. По умолчанию это около 5 минут с jitter.
Кэширование
В API реализован in-memory async cache. Кэш живет внутри процесса API и сбрасывается при перезапуске контейнера.
Кэшируются:
- отдельные датасеты;
- списки датасетов;
- отдельные модели;
- списки моделей;
- отдельные задачи;
- списки задач.
TTL:
- списки -
60секунд; - датасеты -
5 * 60секунд; - модели -
5 * 60секунд; - задачи -
5 * 60секунд; - пользователь -
5 * 60секунд.
К TTL добавляется jitter до 30%, чтобы снизить вероятность одновременного истечения большого числа ключей.
Инвалидация кэша
При создании, удалении и изменении объектов сервисы удаляют точечные ключи и ключи списков по pattern.
Примеры ключей:
dataset:<dataset_id>
model:<model_id>
task:<task_id>
datasets:<user_id>:<skip>:<limit>:<name_filter>
models:<user_id>:<skip>:<limit>:<dataset_id_or_all>
tasks:<user_id>:<skip>:<limit>Консистентность
Система имеет eventual consistency между API, брокером и воркерами. После создания задачи запись в PostgreSQL появляется сразу, но результат будет доступен только после обработки воркером.
Если воркер недоступен, задача останется в queued. Если обработка упала, задача перейдет в failed, а причина будет записана в error_msg.