fix(telegram): back off on transient polling failures
Give getUpdates a wider HTTP timeout than the long-poll window, log transient SSL/network disconnects as warnings, apply exponential backoff with recovery logging, and only escalate to error after five consecutive failures.
This commit is contained in:
1 parent
2d42d8ed55
commit
71a0e8c1d6
3 files changed
+96
-7
No files matched your search
@@ -87,6 +87,7 @@ def test_get_updates_and_answer():
|
||||
data = transport.calls[0]["data"]
|
||||
assert data["offset"] == 99
|
||||
assert data["timeout"] == 17
|
||||
assert transport.calls[0]["timeout"] == 32
|
||||
assert json.loads(data["allowed_updates"]) == ["callback_query"]
|
||||
|
||||
transport = FakeTransport(result=True)
|
||||
@@ -203,6 +204,52 @@ def test_answer_failure_falls_back_to_text():
|
||||
assert bot.edits == [10]
|
||||
|
||||
|
||||
class Recorder:
|
||||
def __init__(self):
|
||||
self.events = []
|
||||
|
||||
def _add(self, level, event, fields):
|
||||
self.events.append((level, event, fields))
|
||||
|
||||
def info(self, event, **fields):
|
||||
self._add("info", event, fields)
|
||||
|
||||
def warning(self, event, **fields):
|
||||
self._add("warning", event, fields)
|
||||
|
||||
def error(self, event, **fields):
|
||||
self._add("error", event, fields)
|
||||
|
||||
def debug(self, event, **fields):
|
||||
self._add("debug", event, fields)
|
||||
|
||||
|
||||
class FlakyBot(FakeBot):
|
||||
def __init__(self):
|
||||
super().__init__([])
|
||||
self.calls = 0
|
||||
|
||||
def get_updates(self, offset=None):
|
||||
self.calls += 1
|
||||
if self.calls < 3:
|
||||
raise OSError("SSL: UNEXPECTED_EOF_WHILE_READING")
|
||||
return []
|
||||
|
||||
|
||||
def test_poller_backoff_and_recovery():
|
||||
sleeps = []
|
||||
recorder = Recorder()
|
||||
bot = FlakyBot()
|
||||
poller = TelegramPoller(
|
||||
bot, FakeActions(), logger=recorder, sleeper=sleeps.append
|
||||
)
|
||||
poller.run_forever(initial_delay=3, max_delay=60, max_iterations=3)
|
||||
assert bot.calls == 3
|
||||
assert sleeps == [3, 6]
|
||||
assert [event[0] for event in recorder.events[:2]] == ["warning", "warning"]
|
||||
assert any(event[1] == "telegram.poll_recovered" for event in recorder.events)
|
||||
|
||||
|
||||
def main():
|
||||
test_format_duration()
|
||||
test_send_candidates_and_chunking()
|
||||
@@ -211,6 +258,7 @@ def main():
|
||||
test_telegram_error_description_preserved()
|
||||
test_poller_dispatch_and_authorization()
|
||||
test_answer_failure_falls_back_to_text()
|
||||
test_poller_backoff_and_recovery()
|
||||
print("OK: Telegram 消息、分片、长轮询与回调授权测试全部通过")
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user