fix(sync): only a refusal about the channel spends its fallback window

A failed connection or token step answered nothing about the channel, yet stamped it: one proxy blip
during an RSS blackout delayed every due channel by a whole window. YouTubeError now names the
endpoint that answered; a failure no endpoint gave, or a spent quota, ends the round and stamps
nothing.
This commit is contained in:
2026-09-19 05:54:19 +02:00
parent 038da5374f
commit a7891d03c5
3 changed files with 27 additions and 12 deletions
+10 -3
View File
@@ -30,7 +30,10 @@ class _FakeYt:
def get_playlist_items(self, playlist_id, page_token=None):
self.calls.append(playlist_id)
if playlist_id in self.failing:
raise YouTubeError("refused", reason=self.failing[playlist_id])
reason = self.failing[playlist_id]
# A request that never got through has no endpoint that answered.
path = "" if reason == "transport" else "playlistItems"
raise YouTubeError("refused", reason=reason, path=path)
cid = "UC" + playlist_id[2:]
return {
"items": [
@@ -134,10 +137,14 @@ def test_a_read_that_fails_waits_the_window_out_too(db, calls):
assert calls == ["UUgone"]
def test_out_of_quota_upstream_stops_the_round(db, calls):
@pytest.mark.parametrize("reason", ["quotaExceeded", "transport"])
def test_a_failure_not_about_the_channel_ends_the_round_and_costs_no_window(db, calls, reason):
# Out of quota, or no connection: every further channel would fail the same way, and a channel
# that was never answered about keeps its turn for the next poll.
_channel(db, "UCa")
_channel(db, "UCb")
_FakeYt.failing["UUa"] = "quotaExceeded"
_FakeYt.failing["UUa"] = reason
assert runner.run_feed_fallback(db, ["UCa", "UCb"])["failed"] == 1
assert calls == ["UUa"]
assert db.get(Channel, "UCa").feed_fallback_at is None