# Задачи Celery Задачи объявлены в `network/base/tasks.py`, `network/base/rating_tasks.py` и `network/analytics/tasks.py`. Расписание собирается в `network/celery.py`. ```{note} Каждая периодическая задача обёрнута в тонкую задачу-обёртку в `network/celery.py`. Это обход [известной проблемы Celery](https://github.com/celery/celery/issues/5059): `shared_task` не регистрируются в планировщике beat напрямую. ``` ## Расписание | Задача | Периодичность | |---|---| | `update_future_observations_with_new_tle_sets` | каждые 30 мин | | `fetch_data` | каждый час | | `fetch_tle` | каждые 4 часа | | `station_log_disconnect` | каждый час | | `notify_for_stations_without_results` | `OBS_NO_RESULTS_CHECK_PERIOD` | | `find_and_rate_failed_observations` | каждые 15 мин | | `update_transmitters_stats` | каждые 15 мин (crontab `*/15`) | | `refresh_statistics_summary` | каждые 5 минут (crontab `*/5`) | | `remove_old_exported_framesets` | каждый час | | `auto_schedule_network(36)` | каждые 12 часов (crontab `0 */12`) | | `check_unknown_satellites` | раз в сутки | | `check_unknown_satellites(True)` | каждые 15 мин | | `calculate_all_satellite_orbital` | ежедневно в 05:00 UTC | | `confirm_satellite_reentries` | ежедневно в 06:00 UTC | | `calculate_all_station_stat` | ежедневно в 03:00 UTC | | `fetch_satellite_from_tle_source_for_all_launches` | ежедневно в 04:00 UTC | | `fetch_launch_supgp` | каждые 2 часа | | `fetch_socrates` | в 00:30, 08:30 и 16:30 UTC | | `sync_launches_from_ll2` | каждые 5 минут (crontab `*/5`) | | `record_launch_first_signals` | каждые 15 мин | | `generate_daily_metrics` | ежедневно в 00:30 UTC | | `backup_database` | ежедневно в 00:00 UTC, **только** при заданном `BACKUP_S3_BUCKET` | | `import_satellite_facts_from_nanosats` | ежедневно в 02:20 UTC | | `import_satellite_facts_from_wikidata` | ежедневно в 02:50 UTC | | `parse_data_from_satnogs` | ежедневно в 01:00 UTC, **только** при `ENVIRONMENT=production` | | `zip_audio_files` | каждые 15 мин, **только** при `ZIP_AUDIO_FILES` и выключенном `USE_S3_STORAGE_FOR_AUDIO` | | `archive_audio_zip_files` | каждый час, **только** при `ARCHIVE_ZIP_FILES` и выключенном `USE_S3_STORAGE_FOR_AUDIO` | Условно регистрируемые задачи — частая причина «задача не выполняется»: см. [](troubleshooting.md). ## Задачи по областям ### Орбитальные данные | Задача | Что делает | |---|---| | `fetch_tle` | Загрузка TLE из всех источников и пересчёт `LatestTleSet` | | `update_future_observations_with_new_tle_sets` | Пересчёт окон будущих наблюдений по свежим TLE | | `calculate_all_satellite_orbital` | Пересчёт орбитальных параметров спутников | | `confirm_satellite_reentries` | Перевод подтверждённо сошедших аппаратов в статус `re-entered` (см. [](satellites.md)) | | `export_tle` | Экспорт наборов TLE | | `fetch_satellite_from_tle_source` | Объекты одного запуска из CelesTrak по номеру COSPAR: у запуска без аппаратов заводит их, у запуска с составом проставляет настоящие номера NORAD по имени. TLE не пишет | | `fetch_satellite_from_tle_source_for_all_launches` | То же для всех **отслеживаемых** запусков (`Launch.is_tracked`) без аппаратов или с неопознанными аппаратами, если пуск не старше 90 суток | | `fetch_launch_supgp` | Состав и TLE запусков из предстартовых файлов SupGP CelesTrak, см. [](launches.md) | | `fetch_socrates` | Сближения спутников портала из CelesTrak SOCRATES, см. [](conjunctions.md) | ### Каталог | Задача | Что делает | |---|---| | `fetch_data` | Спутники и передатчики из SatNOGS DB | | `manual_update_db` | Ручной запуск обновления из SatNOGS DB | | `sync_from_prod` | Каталог стенда из API sonik.space с перезаписью; не запускается при `ENVIRONMENT=production` (см. [](satellites.md)) | | `parse_data_from_satnogs` | Обход наблюдений SatNOGS Network за прошедшие UTC-сутки: по задаче `import_satnogs_observation` на каждое наблюдение с кадрами спутника из каталога | | `import_satnogs_observation` | Кадры одного наблюдения SatNOGS Network: пропускает уже сохранённые, остальные скачивает, сохраняет и сразу декодирует; при сетевой ошибке повторяется | | `check_unknown_satellites` | Поиск объектов, которых нет в базе | | `update_transmitters_stats` | Пересчёт статистики передатчиков | | `import_satellite_facts_from_nanosats` | Паспортные данные наноспутников с nanosats.eu | | `import_satellite_facts_from_wikidata` | Масса, описания и фото из Wikidata и Wikimedia Commons | | `sync_launches_from_ll2` | Календарь запусков из Launch Library 2 — по бюджету 15 запросов в час, живое окно пуска первым (см. [](launches.md)) | | `record_launch_first_signals` | Момент и станция первого сигнала для аппаратов отслеживаемых запусков — один раз, без пересчёта | #### Импорт паспортных данных Обе задачи ходят на чужие серверы, поэтому обе идут **срезами**: за прогон обрабатывается полсотни записей, а место остановки запоминается в кеше. Полный обход nanosats.eu занимает около полутора месяцев — примерно с той же частотой обновляется и сам сайт, а всплеска нагрузки не возникает никогда. Потерянный кеш просто начинает обход заново: все записи идемпотентны. Обе задачи уважают `locked_fields` (см. [](satellites.md)) и пишут только те колонки, которые администратор может заморозить. Соединение с каталогом — **только по номеру NORAD**: страница без него пропускается, потому что совпадение по имени рано или поздно припишет данные не тому аппарату. **Фотографии берутся только из Wikimedia Commons.** С nanosats.eu снимки не скачиваются: их `robots.txt` запрещает каталог с рисунками, а сайт сам сообщает, что права на фотографии ему не принадлежат. Оттуда сохраняются только ссылки `Photo sources` как провенанс. У файла Commons проверяется, что он лежит под `/wikipedia/commons/` — иллюстрация статьи может быть локальной загрузкой en.wikipedia под fair use, и публиковать её нельзя. ### Планирование | Задача | Что делает | |---|---| | `auto_schedule_network` | Автопланирование по сети на заданный горизонт | | `auto_schedule_station_primary` | По основному расписанию станции | | `auto_schedule_station_second` | По дополнительному расписанию станции | | `auto_schedule_station_network` | По общесетевому расписанию | | `launch_scheduler_task` | Планирование наблюдений нового запуска | ### Наблюдения и данные | Задача | Что делает | |---|---| | `process_audio` | Обработка загруженного аудио | | `zip_audio`, `zip_audio_files` | Упаковка аудио в архивы | | `archive_audio_zip_files` | Выгрузка архивов в хранилище | | `clean_observations` | Удаление устаревших наблюдений | | `decode_current_frame` | Декодирование одного кадра | | `decode_recent_data` | Декодирование кадров за неделю, оставшихся без расшифровки. **В расписании нет**: до `1.9.2.1` задача из-за скрытой ошибки ничего не делала, а исправленная идёт по всем таким кадрам внутри одной задачи и не укладывается в лимит времени. Запускается вручную; в расписание вернётся после разбиения по спутникам | | `decode_all_data`, `decode_all_nondecoded_data` | Массовое и повторное декодирование | | `export_frames`, `export_frames_batch`, `export_frames_finalize` | Экспорт наборов кадров | | `remove_old_exported_framesets` | Удаление устаревших выгрузок | ### Станции | Задача | Что делает | |---|---| | `station_log_disconnect` | Запись в журнал станций, ушедших со связи | | `notify_for_stations_without_results` | Уведомление о станциях без результатов | | `calculate_all_station_stat`, `calculate_station_stat` | Пересчёт статистики станций | ### Оценка и аналитика | Задача | Что делает | |---|---| | `find_and_rate_failed_observations` | Проставление `failed` наблюдениям без артефактов | | `rate_observation` | Оценка наблюдения по событию | | `refresh_statistics_summary` | Пересчёт сводных счётчиков сети для главной и страницы статистики: страницы только читают кэш, полный проход по кадрам идёт в воркере | | `generate_daily_metrics` | Суточные метрики за окно в 30 дней | | `backfill_historical_metrics` | Историческое наполнение метрик | ### Резервные копии | Задача | Описание | |---|---| | `backup_database` | `pg_dump --format=custom` базы потоком в бакет `BACKUP_S3_BUCKET`, ключ `/.dump`; при ошибке `pg_dump` неполный объект удаляется и задача падает (см. [](operations.md)) | ## Последний запуск Сигналы `task_prerun`, `task_postrun` и `task_failure` в `network/celery.py` пишут в кеш запись `task-run:<имя задачи>` без срока жизни: начало, конец, длительность, состояние и текст ошибки. Хранится только последний запуск. Сигналы срабатывают для обёртки из `network/celery.py`, а не для `shared_task` внутри неё — по этому имени страница «Система» (см. [](operations.md)) и сопоставляет записи с расписанием beat. Время следующего запуска там — оценка `schedule.remaining_estimate()` от последнего старта: beat ведёт собственный отсчёт в shelve контейнера `celery-beat`, и после его пересоздания оценка и факт расходятся на один интервал. ## Запуск вручную ```bash make djshell ``` ```python from network.base.tasks import fetch_tle fetch_tle.delay() # в очередь fetch_tle() # синхронно, в текущем процессе ``` Часть задач продублирована management-командами — см. [](commands.md). Задачи из расписания можно поставить в очередь со страницы «Система» кнопкой «Запустить» — с теми же аргументами, что у beat.