feat(host_agent): agent 1.10 — backoff inside the stale window, posts of five, a deadline on Docker, /system/df every ten minutes (#5154)

- BACKOFF_CAP 300 → 60: Steward reads a host stale after 180 s, so an agent
  backing off to five minutes read stopped long after Steward came back
  (lesson #4355: a check-in inherits its call's backoff).
- A POST carries at most five samples: the oldest four buffered plus the
  new one, the rest held for the next post. A backlog drains a few at a
  time instead of in one post Steward cannot write before the timeout
  (the loop measured in #5149).
- Per-container Docker work has a 20 s deadline over the whole fan-out.
  Past it the sample reports docker_status "error" ("N of M containers
  not read within 20 s") and no list: a partial list would read as
  removals, and a record without its inspect as restarts.
- /system/df is asked every 600 s rather than every sample; Steward keeps
  the last answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 18:48:28 -04:00
co-authored by Claude Opus 5.5
parent 385a579afe
commit ade078cabf
3 changed files with 97 additions and 15 deletions
@@ -113,11 +113,18 @@ def test_post_payload_network_error_returns_none_status():
assert status is None
def test_backoff_schedule():
def test_backoff_schedule_stays_inside_the_stale_window():
from plugins.host_agent.agent import next_backoff
assert next_backoff(0) == 30
assert next_backoff(30) == 60
assert next_backoff(60) == 120
assert next_backoff(120) == 240
assert next_backoff(240) == 300 # capped
assert next_backoff(300) == 300
assert next_backoff(60) == 60 # capped below Steward's 180 s stale window (#5154)
def test_a_backlog_drains_a_few_samples_a_post_oldest_first():
from plugins.host_agent.agent import MAX_SAMPLES_PER_POST, split_backlog
buffered = list(range(20))
send, held = split_backlog(buffered)
assert send == [0, 1, 2, 3] and held == list(range(4, 20))
assert len(send) + 1 == MAX_SAMPLES_PER_POST # room for the new sample
assert split_backlog([7]) == ([7], [])
assert split_backlog([]) == ([], [])