"""An SNMP poll collects on schedule while the database hangs, and what it held is stored oldest first, each at its own time, once it answers (#5995).""" import asyncio from contextlib import asynccontextmanager from types import SimpleNamespace as NS import plugins.snmp.scheduler as scheduler import plugins.snmp.service as service from plugins.snmp.poller import Credentials, PollResult def _device(): return NS(id="d1", name="nas", address="10.0.0.5", port=161, version="2c", presets=["system"], interfaces="", custom=None, tables={}, tables_at=None, last_error=None, texts={}) def test_polls_go_on_while_the_database_hangs_and_are_stored_in_order_after(monkeypatch): async def main(): stalled = asyncio.Event() @asynccontextmanager async def hung_session(): await stalled.wait() # the storage under Postgres has stalled yield None app = NS(db_sessionmaker=hung_session) gate, stored = asyncio.Event(), [] async def store(app_, rounds): await gate.wait() stored.extend(rounds) uptimes = iter([100.0, 200.0]) async def poll(address, port, creds, oids): return PollResult(readings={"uptime": next(uptimes)}) monkeypatch.setattr(scheduler, "DEVICES", [_device()]) monkeypatch.setattr(scheduler, "DEVICES_READ_S", 0.05) monkeypatch.setattr(scheduler, "STORE_WAIT_S", 0.05) monkeypatch.setattr(scheduler, "_store", store) monkeypatch.setattr(service, "credentials", lambda d: Credentials(community="public")) scheduler.RATES = None await scheduler._do_poll(app, poll=poll) # the device list is the last one read await asyncio.sleep(0.01) await scheduler._do_poll(app, poll=poll) # the first store hasn't returned: polled anyway gate.set() await app._holdings["SNMP poll"].flush(1.0) return stored rounds = asyncio.run(main()) assert [[(p.name, p.values) for p in r] for r in rounds] == [ [("nas", [("uptime", 100.0)])], [("nas", [("uptime", 200.0)])]] assert rounds[0][0].at < rounds[1][0].at # each stored at the time it was collected