fix(sync): R5 S2 — sync guards
- never prune subscriptions on an empty fetch: one anomalous empty-but-200 response wiped every subscription (and its deep_requested flag) in one run - push_playlist: stop after 5 consecutive write failures — a quota-dead or scope-revoked account otherwise burns 50 units per remaining item - RSS: raise RssError instead of returning [] on a transport/HTTP failure, so a failed poll no longer stamps last_rss_at and a 404 feed stops looking healthy - worker: exit when the schema never appears instead of "continuing" into a crash one call later
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
"""Guards that stop one bad YouTube answer from cascading: the playlist-push circuit breaker."""
|
||||
from app.sync.playlists import _Breaker
|
||||
|
||||
|
||||
class TestBreaker:
|
||||
def test_open_until_the_limit_is_reached(self):
|
||||
b = _Breaker(limit=3)
|
||||
for _ in range(2):
|
||||
b.hit(False)
|
||||
assert b.open()
|
||||
b.hit(False)
|
||||
assert not b.open() and b.tripped
|
||||
|
||||
def test_a_success_re_arms_the_streak(self):
|
||||
b = _Breaker(limit=3)
|
||||
b.hit(False)
|
||||
b.hit(False)
|
||||
b.hit(True) # one write went through — this isn't an account-wide failure
|
||||
b.hit(False)
|
||||
b.hit(False)
|
||||
assert b.open()
|
||||
|
||||
def test_stays_tripped_once_tripped(self):
|
||||
b = _Breaker(limit=2)
|
||||
b.hit(False)
|
||||
b.hit(False)
|
||||
b.hit(True)
|
||||
assert not b.open()
|
||||
Reference in New Issue
Block a user