import asyncio from api.utils import gold_refresh, thirdpart_gold def test_both_periodic_jobs_run_without_requests_and_stop_cleanly(monkeypatch): async def run(): calls = [0, 0] ready = [asyncio.Event(), asyncio.Event()] async def realtime(): calls[0] += 1 if calls[0] >= 2: ready[0].set() async def official(): calls[1] += 1 if calls[1] >= 2: ready[1].set() monkeypatch.setattr(gold_refresh, 'refresh_realtime', realtime) monkeypatch.setattr(gold_refresh, 'refresh_official', official) monkeypatch.setattr(gold_refresh, 'CHECK_INTERVAL_SECONDS', .01) try: await gold_refresh.start_periodic_refresh() await gold_refresh.start_periodic_refresh() assert len(gold_refresh._periodic_tasks) == 2 await asyncio.wait_for(asyncio.gather(*(event.wait() for event in ready)), 1) finally: await gold_refresh.stop_periodic_refresh() assert not gold_refresh._periodic_tasks snapshot = list(calls) await asyncio.sleep(.02) assert calls == snapshot asyncio.run(run()) def test_periodic_job_survives_transient_failure(monkeypatch): async def run(): calls = [] ready = asyncio.Event() async def job(): calls.append(1) if len(calls) == 1: raise ConnectionError('Redis unavailable') ready.set() monkeypatch.setattr(gold_refresh, 'CHECK_INTERVAL_SECONDS', .01) task = asyncio.create_task(gold_refresh._periodic(job)) try: await asyncio.wait_for(ready.wait(), 1) assert len(calls) >= 2 finally: task.cancel() await asyncio.gather(task, return_exceptions=True) asyncio.run(run()) def test_realtime_can_launch_without_request_background_tasks(monkeypatch): class Redis: async def get(self, key): return None async def set(self, *args, **kwargs): return True launched = [] async def launch(token): launched.append(token) monkeypatch.setattr(thirdpart_gold, 'launch_refresh', launch) assert asyncio.run(thirdpart_gold.schedule_refresh(Redis(), None, [])) is True assert len(launched) == 1 def test_application_lifecycle_starts_and_stops_refresh_jobs(monkeypatch): import main calls = [] def callback(name): async def call(): calls.append(name) return call monkeypatch.setattr(main, 'start_periodic_refresh', callback('start')) monkeypatch.setattr(main, 'stop_periodic_refresh', callback('stop')) monkeypatch.setattr(main, 'close_refresh_tasks', callback('refresh_closed')) monkeypatch.setattr(main, 'close_connection_pools', callback('pools_closed')) async def run(): async with main.lifespan(main.application): assert calls == ['start'] asyncio.run(run()) assert calls == ['start', 'stop', 'refresh_closed', 'pools_closed']