VEU.WathBody/1-docs/4-modules/m07-fit-fetch/api_specs/02-fetch-cycle.md

2.7 KiB
Raw Blame History

Спецификация 02: FitFetcher — цикл забора и дедупликация

Источники: Ф-8.1, module_reqs разд. 2 (два рубежа дедупа), 🛡3 (сбой одного файла не останавливает пакет).

1. Сигнатура

public FitFetcher(IConnectionString cs, GarminClient client,
    string downloadDir, string athleteName);
public (int Downloaded, int Skipped, int Failed) FetchNew(
    int limit = 20, CancellationToken ct = default);

2. Алгоритм

  1. Атлет: athleteName → src.athlete (первый по имени); не найден → FetchException (CLI переведёт в код 1; 🛡1 — факты без атлета не пишутся).
  2. client.Login() — исключения пробрасываются (без частичного результата).
  3. ListActivities(limit) → фильтр activityType == "strength_training".
  4. Для каждой активности, по порядку списка:
    • downloadDir\{activityId}.fit существует → Skipped++ (рубеж 1 — без сети), далее;
    • скачать → записать во временный файл → FitParser.Parse: сбой → файл остаётся как {activityId}.fit? нет — битый download переносится в {activityId}.fit.bad (не мешает кэшу), Failed++, далее (🛡3);
    • WorkoutImporter.Import(athleteId, facts) — дедуп по fit_file_id внутри (возврат существующего id, записи нет); если это дубль (возврат id существующей строки, файл не новый) → скачанный файл удаляется (рубеж 2, 🛡2), Skipped++;
    • иначе файл переименовывается в {activityId}.fit (кэш), Downloaded++.
  5. Возврат (Downloaded, Skipped, Failed).

3. Ошибки и коды

  • FetchException (атлет/конфигурация) → CLI код 1;
  • GarminAuthException → CLI код 2 + stdout-подсказка «используйте папку импорта (--mode import)» (fallback О-1-А);
  • сбои отдельных файлов → код 2 при Failed > 0.

4. Инварианты 🛡

  • записи в БД — только через WorkoutImporter (конвейер m06);
  • изоляция: факты пишутся только athleteId атлета-владельца учётки;
  • повторный запуск не качает дубли и не создаёт дублей в БД.