Детали реализации
Структура базы данных
Таблица Album
Хранит информацию об альбомах и настройках распознавания.
Поля:
AlbumId— идентификатор альбомаTenantId— идентификатор тенантаName— название альбомаEventDate— дата событияCreatedOn,UpdatedOn,Version— системные поляStrategy- стратегия распознавания (строка, название пайплайна)State— состояние распознавание (включено/выключено)StartNumberCapacity— разрядность номеровNormalizationPolicy— политика нормализации номеровPriority— приоритет обработки
Таблица Photo
Хранит информацию о фотографиях и состоянии их распознавания.
Поля:
PhotoId— идентификатор фотографииAlbumId— идентификатор альбомаState— состояние обработки фотографииCreatedOn,UpdatedOn,Version— системные поляReasonDescription— описание причины текущего состояния- Признаки распознавания (добавляются):
FaceRecognized— лица распознаныNumberRecognized— номера распознаны
Признаки распознавания нужны для того, чтобы при смене стратегии распознавания выбирать из базы только фотографии, которые нужно распознать в новой стратегии. Например, если новая стратегия предполагает распознавание и лиц, и номеров, нужно выбрать все, у которых не распознаны лица или номера. Проблема в том, что могли уже отдать фотографию на распознавание номеров, но ожидаем колбек, и в этот момент изменили стратегию на ту, которая требует распознавания номеров. С одной стороны, номера еще не распознаны, поэтому нужно выбрать эту фотографию. С другой стороны, нет смысла ее снова обрабатывать, т.к. ожидаем колбека. С третьей стороны, могли авто распознавание (с колбеком) заменить на ручное распознавание (например, если колбеки уже не придут), тогда фото все же нужно взять. Поэтому оставляем пока с этой проблемой. Нет колбека - номера не распознаны - обрабатываем фото.
Таблица Tenant
Хранит информацию о тенантах.
Поля:
TenantId— идентификатор тенантаRecognitionState— состояние распознаванияCreatedOn,UpdatedOn,Version— системные поля
Таблицы без изменений
Следующие таблицы переносятся без изменений:
- AlbumCustomTag — кастомные теги для альбомов
- Callback — колбеки от Athlete
- Account — аккаунты VkVision
- AccountSpace — спейсы VkVision
- PhotoPerson — связь фото и персон
Интерфейс Athlete (Eldarius)
Запрос на распознавание
Тип распознавания:
recognition_type = FACE_NUMBER
Одним запросом получаем и лица, и номера.
Callback
public sealed class CallbackPayloadBinding
{
[Required]
[JsonPropertyName("persons")]
public IEnumerable<CallbackPersonBinding> Persons { get; set; } = null!;
[Required]
[JsonPropertyName("tags")]
public IEnumerable<CallbackPersonBinding> Tags { get; set; } = null!;
}
API сервиса
AdminApi
AlbumController
GET /api/v{version}/albums/{albumId}
Получить альбом по ID.
Аутентификация: требуется роль recognition.manage.
Параметры маршрута:
albumId: guid— идентификатор альбома
Ответы:
200 OK:
{
"name": "string",
"startNumbersRecognitionStrategy": "string",
"startNumberCapacity": 0,
"normalizationPolicy": "string",
"priority": 0,
"eventDate": "2024-01-01T00:00:00Z",
"createdOn": "2024-01-01T00:00:00Z",
"updatedOn": "2024-01-01T00:00:00Z",
"allowedStrategies": ["string"],
"allowedFaceProviders": [
{
"name": "string",
"providerId": "guid"
}
],
"recognition": {
"faceProviderId": "guid",
"faceProviderSpaceId": "guid"
}
}
404 Not Found — альбом не найден.
Обновления:
- Из
allowedFaceProvidersбудет удален провайдерDisabled. Фронт сам должен добавить этот вариант, и если он выбран, передать null в метод изменения настроек распознавания. - Поля
recognitionStrategyиtaggingStrategyсейчас сохранены для обратной совместимости, но будут удалены, вместо них - полеstartNumbersRecognitionStrategy. - Поле
allowedStrategiesсейчас сохранено для обратной совместимости, но будет удалено, вместо него - полеallowedStartNumbersRecognitionStrategies.
PATCH /api/v{version}/albums/{albumId}/priority
Изменить приоритет альбома.
Аутентификация: требуется роль recognition.manage.
Параметры маршрута:
albumId: guid— идентификатор альбома
Тело запроса:
{
"priority": 0
}
Поле priority является обязательным ([Required]).
Ответы:
204 No Content— приоритет успешно изменён404 Not Found— альбом не найден409 Conflict— конфликт версий (оптимистичная блокировка)422 Unprocessable Entity— невалидные данные
PATCH /api/v{version}/albums/{albumId}/recognition/settings
Изменить настройки распознавания альбома.
Аутентификация: требуется роль recognition.manage.
Параметры маршрута:
albumId: guid— идентификатор альбома
Тело запроса:
Текущий вид биндинга (для обратной совместимости — поля nullable):
{
"providerId": "guid",
"providerSpaceId": "guid",
"startNumbersRecognitionStrategy": "string | null",
"normalizationPolicy": "string | null",
"startNumberCapacity": "integer | null"
}
После исправления фронтенда поля startNumbersRecognitionStrategy, normalizationPolicy и startNumberCapacity станут обязательными:
{
"providerId": "guid",
"providerSpaceId": "guid",
"startNumbersRecognitionStrategy": "string",
"normalizationPolicy": "string",
"startNumberCapacity": 0
}
Поведение:
- Если
startNumbersRecognitionStrategy == null(режим обратной совместимости): изменяется только провайдер лица (ChangeAlbumFaceProviderCommand). ПоляnormalizationPolicyиstartNumberCapacityигнорируются. - Если
startNumbersRecognitionStrategyуказан: изменяются все настройки распознавания (ChangeAlbumRecognitionSettingsCommand). - Если нужно отключить распознавание лиц, нужно передавать providerId=null.
Ответы:
204 No Content— настройки успешно изменены404 Not Found— альбом или провайдер не найден409 Conflict— конфликт версий (оптимистичная блокировка)422 Unprocessable Entity— невалидные данные
SettingsController
Эндпоинты:
PATCH /api/v{version}/settings/{tagatorId}/changeTagatorSettings— изменить настройки тегатораGET /api/v{version}/settings/{tagatorId}/tagatorSettings— получить настройки тегатора
TenantsController
Эндпоинты:
GET /api/v{version}/tenants/{tenantId}— получить тенант по IDPUT /api/v{version}/tenants/{tenantId}/recognition— включить/выключить распознавание для тенанта
StatisticController
Эндпоинты:
GET /api/v{version}/statistics/byAlbums— статистика по альбомамGET /api/v{version}/statistics/timeSheetsByInterval— статистика табелей по интервалам
TagatorController
Эндпоинты:
POST /api/v{version}/tagators— создать тегатораPATCH /api/v{version}/tagators/{tagatorId}— изменить тегатораPOST /api/v{version}/tagators/{tagatorId}/password— изменить пароль тегатораGET /api/v{version}/tagators/{tagatorId}— получить тегатора по IDGET /api/v{version}/tagators/{tagatorId}/statistic— статистика тегатораPOST /api/v{version}/tagators/tagator-report— отчет по тегаторамGET /api/v{version}/tagators— список тегаторов с пагинациейPOST /api/v{version}/tagators/invitation-tagging— пригласить тегаторов
TagatorTasksController
Эндпоинты:
POST /api/v{version}/tasks/callback— колбек завершения задачи тегирования
SelfiesController
Эндпоинты:
POST /api/v{version}/selfies— распознать селфи
AccountsController
Эндпоинты:
POST /api/v{version}/accounts— создать аккаунт VkVisionPATCH /api/v{version}/accounts/{accountId}— изменить аккаунтGET /api/v{version}/accounts— список аккаунтовGET /api/v{version}/accounts/{accountId}— получить аккаунт по IDPUT /api/v{version}/accounts/{accountId}/active— изменить состояние аккаунтаGET /api/v{version}/accounts/{accountId}/spaces— получить спейсы аккаунтаGET /api/v{version}/accounts/{accountId}/spaces/{accountSpaceId}— получить спейс по IDPOST /api/v{version}/accounts/{accountId}/spaces— добавить спейсPATCH /api/v{version}/accounts/{accountId}/spaces/{accountSpaceId}— изменить спейсPUT /api/v{version}/accounts/{accountId}/spaces/{accountSpaceId}/active— изменить состояние спейса
ClientApi
SelfiesController
Эндпоинты:
POST /api/v{version}/selfies— распознать селфиGET /api/v{version}/selfies/{selfieId}— получить детали селфи
AvatarTasksController
Эндпоинты:
POST /api/v{version}/avatar/tasks/callback— колбек задачи распознавания аватара
EldariusTasksController
Эндпоинты:
POST /api/v{version}/auto-tagging/tasks/callback— колбек задачи автотегирования
TagatorAccountController
Эндпоинты:
POST /api/v{version}/accounts/signin— вход тегатораGET /api/v{version}/accounts— получить данные аккаунта
AlbumsController
Эндпоинты:
GET /api/v{version}/albums/{albumId}/customTags— получить кастомные тегиGET /api/v{version}/albums/{albumId}/taggingHint— получить подсказку для тегирования
TagatorWorksController
Эндпоинты:
POST /api/v{version}/works— создать работу тегатораGET /api/v{version}/works/current— получить текущую работуGET /api/v{version}/works/{tagatorWorkId}— получить работу по IDGET /api/v{version}/works/{tagatorWorkId}/tasks— получить задачи работыPUT /api/v{version}/works/{tagatorWorkId}/tasks/{taggingTaskId}/complete— завершить задачуPOST /api/v{version}/works/{tagatorWorkId}/tasks/{taggingTaskId}/tags— добавить тегиDELETE /api/v{version}/works/{tagatorWorkId}/tasks/{taggingTaskId}/tags— удалить теги
InternalApi
AlbumController
Эндпоинты:
GET /api/v{version}/albums/{albumId}— получить альбом по IDGET /api/v{version}/albums/{albumId}/counter/photos— количество фото по статусу
TagatorsController
Эндпоинты:
GET /api/v{version}/tagators/{tagatorId}— получить тегатора по ID
StatisticsController
Эндпоинты:
GET /api/v{version}/statistics/tagators— статистика тегаторов
Команды и обработчики
Переписываемые джобы
AlbumPhotosProcessingJob
Текущая логика:
- Перебирает все фотографии альбома
- Создает задачи на обработку
Новая логика:
- Выбирает только фото, требующие обработки согласно стратегии
- Использует признаки состояния распознавания (
FaceRecognized,NumberRecognized) - Учитывает наличие тегов и персон
- Обрабатывает только необходимые фото
Команды обработки
Обработка PhotoPublished
Процесс:
- Создать локальную запись фотографии
- Определить стратегию альбома
- Обработать фото сразу (синхронно):
- Для VkVision — распознать лица и сохранить результат
- Для Athlete — отправить запрос на распознавание
- Для ручного — создать задачу тегирования
- При ошибке — создать Hangfire-джобу для повторной обработки
- Завершить подписку
Обработка PhotoDeleted
Процесс:
- Отменить задачи тегирования через InternalApi
- Выполнить команду
CancelTaggingTaskCommand
Интеграция с другими сервисами
PhotoService
Отправка результатов:
- Персоны (лица) — после распознавания в VkVision или получения callback от Athlete
- Теги (номера) — после распознавания в Athlete или завершения ручного тегирования
TagatorService
Создание задач:
- Передача
PhotoId,AlbumId,PhotographerId,ShootingDate - Назначение приоритета
- Контроль состояния задач
Отмена задач:
- При удалении фото
- При изменении стратегии (если задача больше не нужна)
CompetitorService
Обращение:
- Определить инстанс CompetitorService по настройкам проекта/тенанта
- Выполнить запрос к соответствующему инстансу
- Получить стартовый список для валидации
Миграция данных
Этапы миграции
-
Подготовка:
- Создать новую БД для сервиса распознавания
- Развернуть схему БД
-
Миграция данных:
- Объединить данные из RecognitionService и TaggingService
- Перенести альбомы, фотографии, задачи
- Объединить дублирующиеся записи
- Проверить целостность данных
-
Синхронизация:
- Настроить синхронизацию новых данных в процессе миграции
- Обеспечить консистентность
-
Переключение:
- Развернуть новый сервис
- Переключить маршрутизацию запросов
- Остановить старые сервисы
Скрипты миграции
Требуется разработать SQL-скрипты для:
- Создания структуры БД
- Переноса данных из RecognitionService
- Переноса данных из TaggingService
- Объединения дублирующихся записей
- Проверки целостности
Технические доработки
Удаление джоб отмены задач
После объединения сервисов:
- Убрать джобы отмены задач при удалении фото
- Использовать прямой вызов метода InternalApi
- Выполнять команду
CancelTaggingTaskCommand
Аналогично для RejectTagatorTaggingTasksJob.
Валидация и разрядность
- Валидация результатов по стартовому списку сохраняется
- Учет разрядности номеров в Athlete сохраняется
Команды, квери и джобы
Сохранить из текущих сервисов:
- Команды создания, обновления, удаления сущностей
- Квери получения данных
- Джобы фоновой обработки
Внести изменения:
- Интеграция с Athlete для получения
personsиtags - Переработка
AlbumPhotosProcessingJob - Оптимизация обработки фото (устранение промежуточных статусов)
- Команды для работы с аккаунтами и спейсами VkVision
Развертывание
Конфигурация (неправильно)
Добавить конфигурационные файлы:
appsettings.json— основные настройкиappsettings.Development.json— настройки для devappsettings.Production.json— настройки для prod
CI/CD
Добавить:
.gitlab-ci.yml— пайплайн сборки и деплояDockerfile— образ для контейнеризации
Helm Charts
Создать charts для развертывания в Kubernetes:
- Deployment
- Service
- ConfigMap
- Secrets
- Ingress