fix(sync): the stored RSS warning says what the API fallback read
An INFO line outside a request never reaches log_events, so the fallback's own summary was invisible in the Server log. Its counts ride on the sync.rss.failed warning, the one line of a poll the console keeps. Measured on localdev: 375 of 375 dark channels read, 403 new videos.
This commit is contained in:
@@ -152,16 +152,22 @@ def run_rss_poll(db: Session, channels: list[Channel] | None = None) -> dict[str
|
|||||||
progress.report(done, total, "rss_poll")
|
progress.report(done, total, "rss_poll")
|
||||||
fallback = run_feed_fallback(db, unread)
|
fallback = run_feed_fallback(db, unread)
|
||||||
if failed:
|
if failed:
|
||||||
|
# The fallback's count rides on this line because this is the one the stored log keeps (an
|
||||||
|
# INFO line outside a request never reaches `log_events`): the console should show whether
|
||||||
|
# the uploads came in another way.
|
||||||
log.warning(
|
log.warning(
|
||||||
"RSS poll: %d/%d channels could not be polled",
|
"RSS poll: %d/%d channels could not be polled; %d read through the API instead",
|
||||||
failed,
|
failed,
|
||||||
total,
|
total,
|
||||||
|
fallback["read"],
|
||||||
extra=logs.event(
|
extra=logs.event(
|
||||||
"sync.rss.failed",
|
"sync.rss.failed",
|
||||||
failed=failed,
|
failed=failed,
|
||||||
total=total,
|
total=total,
|
||||||
reasons=dict(reasons),
|
reasons=dict(reasons),
|
||||||
examples=examples,
|
examples=examples,
|
||||||
|
fallback_read=fallback["read"],
|
||||||
|
fallback_new=fallback["new"],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if total and failed == total:
|
if total and failed == total:
|
||||||
|
|||||||
@@ -235,7 +235,9 @@ class TestRssPollResult:
|
|||||||
with pytest.raises(RuntimeError, match="read-only transaction"):
|
with pytest.raises(RuntimeError, match="read-only transaction"):
|
||||||
self._run(monkeypatch, fetch=lambda cid: [{"id": "v"}], apply_=boom)
|
self._run(monkeypatch, fetch=lambda cid: [{"id": "v"}], apply_=boom)
|
||||||
|
|
||||||
def test_only_the_unreadable_feeds_go_to_the_api_and_what_it_reads_counts(self, monkeypatch):
|
def test_only_the_unreadable_feeds_go_to_the_api_and_what_it_reads_counts(
|
||||||
|
self, monkeypatch, caplog
|
||||||
|
):
|
||||||
# A feed that answered 404 is the fallback's; a channel whose rows failed to STORE is not —
|
# A feed that answered 404 is the fallback's; a channel whose rows failed to STORE is not —
|
||||||
# the API would hand the same rows to the same broken write.
|
# the API would hand the same rows to the same broken write.
|
||||||
seen = []
|
seen = []
|
||||||
@@ -262,6 +264,9 @@ class TestRssPollResult:
|
|||||||
)
|
)
|
||||||
assert seen == ["UC_dark"]
|
assert seen == ["UC_dark"]
|
||||||
assert out == {"new": 4, "failed": 2, "fallback": 1}
|
assert out == {"new": 4, "failed": 2, "fallback": 1}
|
||||||
|
# ...and the one line the stored log keeps says so (an INFO line outside a request is not).
|
||||||
|
(warning,) = [r for r in caplog.records if getattr(r, "event", None) == "sync.rss.failed"]
|
||||||
|
assert warning.attrs["fallback_read"] == 1 and warning.attrs["fallback_new"] == 3
|
||||||
|
|
||||||
def test_no_channels_at_all_is_not_an_outage(self, monkeypatch):
|
def test_no_channels_at_all_is_not_an_outage(self, monkeypatch):
|
||||||
# A fresh instance with nothing subscribed must not report an error every poll.
|
# A fresh instance with nothing subscribed must not report an error every poll.
|
||||||
|
|||||||
Reference in New Issue
Block a user