fix(agent): полная пауза при времени журнала в будущем, claim без оценки из журнала (#15)
M-6, M-7 (agent#12). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0532b2476c
commit
3736fb3948
12
src/agent.py
12
src/agent.py
@ -940,7 +940,9 @@ class Runner:
|
||||
|
||||
def restore_pace(self) -> None:
|
||||
"""После перезапуска время последнего вызова Jira неизвестно (живёт в памяти). Берём самое позднее время записи
|
||||
журнала: finished пишется сразу после последнего вызова команды, оценка не раньше настоящего вызова (M-9)."""
|
||||
журнала: finished пишется сразу после последнего вызова команды, оценка не раньше настоящего вызова (M-9).
|
||||
Время в будущем (часы ушли назад) — считаем «сейчас»: пауза полная (M-6 #12). Оценка служит только паузе:
|
||||
last_call_iso (уходит хабу в claim) ставит лишь настоящий вызов Jira (M-7 #12)."""
|
||||
if self.jira.last_call_at is not None:
|
||||
return
|
||||
at = self.journal.last_at()
|
||||
@ -948,11 +950,11 @@ class Runner:
|
||||
return
|
||||
ago = (datetime.now(timezone.utc) - at).total_seconds()
|
||||
if ago < 0:
|
||||
log("журнал: время последней записи в будущем (%s) — темп не восстанавливаю" % at.isoformat())
|
||||
return
|
||||
log("журнал: время последней записи в будущем (%s) — пауза перед первой командой полная" % at.isoformat())
|
||||
ago = 0
|
||||
self.jira.last_call_at = time.monotonic() - ago
|
||||
self.jira.last_call_iso = at.astimezone(timezone.utc).replace(microsecond=0).isoformat()
|
||||
log("темп: последний вызов Jira не позже %s (по журналу)" % self.jira.last_call_iso)
|
||||
log("темп: последний вызов Jira не позже %s (по журналу)"
|
||||
% at.astimezone(timezone.utc).replace(microsecond=0).isoformat())
|
||||
|
||||
def send_result(self, rec: dict) -> bool:
|
||||
"""Отчёт хабу; повторяется каждые 10 с, пока хаб не подтвердит. 404/409/422 — хаб отверг (команда отменена
|
||||
|
||||
@ -16,6 +16,7 @@ class FakeHub:
|
||||
self.states = []
|
||||
self.known = []
|
||||
self.claims = 0
|
||||
self.claim_bodies = []
|
||||
self.fail_results = 0
|
||||
self.reject_results = {}
|
||||
self.in_flight = None
|
||||
@ -68,6 +69,7 @@ class FakeHub:
|
||||
|
||||
def route(self, method, path, body):
|
||||
if path == "/agent/claim":
|
||||
self.claim_bodies.append(body or {})
|
||||
self.claims += 1
|
||||
if self.in_flight and self.commands[self.in_flight]["status"] == "claimed":
|
||||
return 200, {"command": None, "settings_version": self.settings["settings_version"]}
|
||||
|
||||
@ -60,14 +60,23 @@ class RunnerTest(unittest.TestCase):
|
||||
self.runner.loop()
|
||||
self.assertAlmostEqual(sum(self.sleeps), 20, delta=1.5)
|
||||
|
||||
def test_future_journal_time_ignored(self):
|
||||
at = (datetime.now(timezone.utc) + timedelta(hours=1)).replace(microsecond=0).isoformat()
|
||||
def test_future_journal_time_means_full_pause(self):
|
||||
at = (datetime.now(timezone.utc) + timedelta(hours=2)).replace(microsecond=0).isoformat()
|
||||
self.journal.append({"kind": "acked", "command_id": 99, "at": at})
|
||||
self.hub.enqueue("ensure_fields", {"key": "AURORA-1", "duedate": "2026-10-23"}, pause=30)
|
||||
self.runner.loop()
|
||||
self.assertEqual(self.sleeps, []) # время из будущего — как пустой журнал
|
||||
self.assertAlmostEqual(sum(self.sleeps), 30, delta=1.5) # часы ушли назад — пауза полная (M-6 #12)
|
||||
self.assertEqual(self.hub.results[1]["status"], "done")
|
||||
|
||||
def test_claim_after_restart_sends_no_journal_estimate(self):
|
||||
at = (datetime.now(timezone.utc) - timedelta(seconds=10)).replace(microsecond=0).isoformat()
|
||||
self.journal.append({"kind": "acked", "command_id": 99, "at": at})
|
||||
self.hub.enqueue("ensure_fields", {"key": "AURORA-1", "duedate": "2026-10-23"})
|
||||
self.runner.loop()
|
||||
self.assertIsNone(self.hub.claim_bodies[0].get("last_jira_call_at")) # оценка журнала — только для паузы (M-7 #12)
|
||||
self.assertIsNotNone(self.hub.claim_bodies[-1].get("last_jira_call_at")) # после вызова Jira — настоящее время
|
||||
self.assertIsNotNone(self.runner.jira.last_call_at)
|
||||
|
||||
def test_restore_pace_keeps_existing_last_call(self):
|
||||
at = (datetime.now(timezone.utc) - timedelta(seconds=100)).replace(microsecond=0).isoformat()
|
||||
self.journal.append({"kind": "acked", "command_id": 99, "at": at})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user