34 lines
1.9 KiB
Markdown
34 lines
1.9 KiB
Markdown
# Спецификация: вызов MetricsEngine из sync (m02)
|
||
|
||
> Ф-12.1: «после каждой синхронизированной тренировки MetricsEngine
|
||
> считает метрики». Точка вызова — `SyncService.Process`
|
||
> (Server.WatchBody.Web) после `scope.Complete()`.
|
||
|
||
## 1. Поток
|
||
|
||
1. `WebAppStartup`: `MetricsEngine` регистрируется синглтоном (те же
|
||
репозитории, что у sync); `MetricsConfig` — синглтоном из конфига.
|
||
2. `SyncService.Process`: собирает список уникальных `workout_id`,
|
||
затронутых пакетом (элемент `entity=workout`, успех = id из
|
||
`workout_insert`/повтор существующего).
|
||
3. После `scope.Complete()` (транзакция пакета зафиксирована) —
|
||
для каждого затронутого `workout_id`:
|
||
`metricsEngine.ComputeForWorkout(athleteId, workoutId)` в
|
||
`try/catch (Exception)`:
|
||
- успех — Debug-лог;
|
||
- исключение — Warning-лог с `workout_id` и сообщением,
|
||
обработка пакета продолжается (🛡4: sync остаётся принятым,
|
||
ответ 200 не меняется).
|
||
4. Пакет без `workout`-элементов → MetricsEngine не вызывается.
|
||
|
||
## 2. Пересчёт
|
||
|
||
Повторный sync того же пакета (идемпотентность) повторяет расчёт —
|
||
upsert обновляет строку, `computed_at` свежее (🛡2, приёмка №2).
|
||
|
||
## 3. Что не меняется
|
||
|
||
Контракт POST /api/v1/sync (spec m02 03-sync-post) — без изменений:
|
||
метрики в ответ sync не входят; телефон читает их отдельным
|
||
средством (workout card / v2 endpoint — вне m04).
|