diff --git a/plugins/alert.py b/plugins/alert.py index 452f8e6..13a612f 100644 --- a/plugins/alert.py +++ b/plugins/alert.py @@ -5,6 +5,7 @@ from __future__ import annotations import asyncio import json import re +import ssl import urllib.request from datetime import datetime, timezone @@ -271,11 +272,22 @@ async def _poll_once(bot, key: str, announce: bool = True) -> None: loop = asyncio.get_running_loop() for tag, backend in _BACKENDS.items(): - try: - items = await loop.run_in_executor(None, backend, keyword) - except Exception as exc: - data["last_error"] = f"{tag}: {exc}" - had_error = True + items = None + for attempt in range(3): + try: + items = await loop.run_in_executor(None, backend, keyword) + break + except (ssl.SSLError, ConnectionError, TimeoutError, OSError) as exc: + if attempt < 2: + await asyncio.sleep(2 ** attempt) + continue + data["last_error"] = f"{tag}: {exc}" + had_error = True + except Exception as exc: + data["last_error"] = f"{tag}: {exc}" + had_error = True + break + if items is None: continue seen_set = set(data.get("seen", {}).get(tag, [])) diff --git a/tests/test_alert.py b/tests/test_alert.py index c3881d5..ef393f8 100644 --- a/tests/test_alert.py +++ b/tests/test_alert.py @@ -1220,7 +1220,7 @@ class TestSearchSearx: def close(self): pass - with patch.object(_mod, "_urlopen", return_value=FakeResp()): + with patch("urllib.request.urlopen", return_value=FakeResp()): results = _search_searx("test query") assert len(results) == 3 assert results[0]["id"] == "https://example.com/sx1" @@ -1237,13 +1237,13 @@ class TestSearchSearx: def close(self): pass - with patch.object(_mod, "_urlopen", return_value=FakeResp()): + with patch("urllib.request.urlopen", return_value=FakeResp()): results = _search_searx("nothing") assert results == [] def test_http_error_propagates(self): import pytest - with patch.object(_mod, "_urlopen", side_effect=ConnectionError("fail")): + with patch("urllib.request.urlopen", side_effect=ConnectionError("fail")): with pytest.raises(ConnectionError): _search_searx("test")