"""Collected rounds held in memory until the database takes them (#5995): stored oldest first, one writer at a time, bounded, and kept through a store that fails or never answers.""" import asyncio from types import SimpleNamespace as NS from steward.core.holding import Holding, holding def test_rounds_held_while_the_store_hangs_are_stored_in_order_once_it_answers(): async def main(): gate, stored = asyncio.Event(), [] async def store(rounds): await gate.wait() stored.append(list(rounds)) held = Holding("t", store, limit=10) held.hold("a") assert await held.flush(0.05) is False # the store hangs: the caller goes on held.hold("b") assert await held.flush(0.05) is False and len(held) == 2 gate.set() assert await held.flush(1.0) is True and len(held) == 0 return stored assert asyncio.run(main()) == [["a"], ["b"]] # "b" waited for the store in flight def test_past_its_limit_the_oldest_round_goes_and_is_counted(): held = Holding("t", store=None, limit=2) for r in ("a", "b", "c"): held.hold(r) assert len(held) == 2 and held.dropped == 1 and [i for _, i in held._held] == ["b", "c"] def test_a_store_that_fails_or_overruns_its_deadline_keeps_the_rounds_held(): async def main(): calls = [] async def failing(rounds): calls.append(list(rounds)) raise RuntimeError("database refused") held = Holding("t", failing, limit=10) held.hold("a") assert await held.flush(1.0) is False and len(held) == 1 async def never(rounds): await asyncio.sleep(3600) stuck = Holding("t", never, limit=10, deadline_s=0.05) stuck.hold("a") assert await stuck.flush(1.0) is False and len(stuck) == 1 # given up, not lost return calls assert asyncio.run(main()) == [["a"]] def test_an_app_has_one_holding_per_collector(): app = NS() first = holding(app, "SNMP poll", store=None, limit=5) assert holding(app, "SNMP poll", store=None, limit=5) is first assert holding(app, "UniFi poll", store=None, limit=5) is not first