6.4 KiB
MODIFIED Requirements
Requirement: Цикл выполнения
Агент SHALL работать одним процессом: claim к хабу (долгий запрос) → при получении команды: досыпать до
pause_seconds от последнего вызова Jira → запись «started» в журнал → выполнение по контракту commands → запись
«finished» с результатом → отчёт хабу, повторяемый до подтверждения. Одна команда в полёте: новый claim агент SHALL
отправлять, только когда у него нет выданной, но не завершённой и не отчитанной команды (на этом хаб строит повторную
выдачу, см. commands). Один процесс на журнал: run SHALL брать исключительную блокировку файла <журнал>.lock и,
если она занята, завершаться с кодом 1 и сообщением «агент уже запущен». При изменении settings_version в ответе claim агент SHALL перечитать настройки до выполнения
команды.
Scenario: Остановка между командами
- WHEN получен Ctrl-C во время выполнения команды
- THEN текущая команда доделывается и отчёт отправляется, затем процесс завершается
Scenario: Второй процесс с тем же журналом
- WHEN агент работает, и запускается ещё один
agent.py runс тем жеjournal.jsonl - THEN второй процесс пишет «агент уже запущен…» и завершается с кодом 1, не обращаясь к хабу и Jira
Requirement: Журнал на диске и восстановление
Агент SHALL вести journal.jsonl (только дозапись) рядом с собой: строки claimed {command_id, at} (сразу после
получения команды, до паузы), started {command_id, at}, finished {command_id, status, result, error, jira_calls, rate_limited, at}, acked {command_id, at}. При старте агент SHALL: отправить хабу все finished без acked; для
claimed/started без finished — запросить команду у хаба по id и, если она в хабе всё ещё claimed, выполнить её
заново по правилу «проверь, потом сделай» с паузой pause_seconds из ответа хаба, не записывая claimed повторно.
Команда python3 agent.py prune SHALL удалять из журнала записи с acked старше 30 дней.
Scenario: Падение после ответа Jira
- WHEN агент упал между
POST /issueи записьюfinished, затем перезапущен - THEN агент находит в журнале
startedбезfinished, запрашивает команду у хаба, находит созданную задачу поиском дубля и отчитываетсяdoneс её ключом; второй задачи нет
Scenario: Восстановление без лишней записи
- WHEN в журнале
claimed 40безfinished, хаб отдаёт команду 40 вclaimedсpause_seconds = 30 - THEN в журнал дописываются
started 40,finished 40,acked 40; второй строкиclaimed 40нет; перед выполнением агент выдерживает 30 с от последнего вызова Jira
Requirement: Ограничение темпа и 429
Агент SHALL помнить время последнего вызова Jira (любого) и не начинать команду раньше pause_seconds после него. При
старте агент SHALL принять за время последнего вызова Jira самое позднее at в журнале (если оно не в будущем); при пустом
журнале паузы перед первой командой нет. На HTTP 429 и 503 агент SHALL ждать Retry-After (иначе 60 с × номер попытки)
и повторять тот же запрос до 5 раз, считая попытки в rate_limited; после 5 неудач — failed. Пауза между записями
внутри одной команды — по зазору типа команды.
Scenario: 429 с Retry-After
- WHEN Jira ответила 429 с
Retry-After: 90 - THEN агент ждёт 90 с, повторяет тот же запрос; в отчёте
rate_limited = 1
Scenario: Перезапуск не сбивает темп
- WHEN последняя запись журнала
finishedсделана 10 с назад, агент перезапущен и получил команду сpause_seconds = 30 - THEN агент ждёт около 20 с перед первым вызовом Jira по команде
Requirement: Доставка и запуск
README агента SHALL описывать: копирование agent.py и agent.example.json через общую папку, заполнение agent.json
(включая выбор транспорта в hub_url), check, запуск в терминале и через nohup с логом, опциональный launchd-plist,
prune. Версия агента SHALL быть в константе файла (3 — с восстановлением темпа после перезапуска и блокировкой одного процесса) и в каждом отчёте;
хаб предупреждает в agent_status, если версия ниже минимальной из настроек.
Scenario: Устаревший агент
- WHEN агент версии 1 выходит на связь, а в настройках
min_agent_version = 2 - THEN
agent_status.warning= «обновите агента», команды выдаются по-прежнему