Add queue deduplication to prevent duplicate entries
- In-memory dedup in add_to_queue() using _pending_by_episode dict - Batch-local dedup via seen_in_batch set (handles duplicates within single call) - Database unique index on episode_id via __table_args__ - 5-minute cooldown in _auto_download_missing() to prevent rapid re-triggers - Updated _add_to_pending_queue() and _remove_from_pending_queue() to track episode keys - Added TestQueueDeduplication with 4 test cases - Updated DEVELOPMENT.md and TESTING.md with queue dedup docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -834,3 +834,111 @@ class TestRemoveEpisodeFromMissingList:
|
||||
# Episode 2 should be removed from in-memory missing list
|
||||
assert 2 not in serie.episodeDict[1]
|
||||
assert serie.episodeDict[1] == [1, 3]
|
||||
|
||||
|
||||
class TestQueueDeduplication:
|
||||
"""Test queue deduplication to prevent duplicate entries."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_same_episode_twice_creates_only_one_entry(
|
||||
self, download_service
|
||||
):
|
||||
"""Test that adding the same episode twice only creates one queue entry."""
|
||||
episodes = [EpisodeIdentifier(season=1, episode=1)]
|
||||
|
||||
# Add same episode twice
|
||||
ids1 = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes,
|
||||
)
|
||||
ids2 = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes,
|
||||
)
|
||||
|
||||
# Should only have one entry
|
||||
assert len(download_service._pending_queue) == 1
|
||||
# First call creates one ID
|
||||
assert len(ids1) == 1
|
||||
# Second call creates zero IDs (deduplicated)
|
||||
assert len(ids2) == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_different_episodes_creates_separate_entries(
|
||||
self, download_service
|
||||
):
|
||||
"""Test that different episodes create separate queue entries."""
|
||||
episodes1 = [EpisodeIdentifier(season=1, episode=1)]
|
||||
episodes2 = [EpisodeIdentifier(season=1, episode=2)]
|
||||
|
||||
ids1 = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes1,
|
||||
)
|
||||
ids2 = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes2,
|
||||
)
|
||||
|
||||
# Should have two separate entries
|
||||
assert len(download_service._pending_queue) == 2
|
||||
assert len(ids1) == 1
|
||||
assert len(ids2) == 1
|
||||
# IDs should be different
|
||||
assert ids1[0] != ids2[0]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_same_episode_different_series_creates_entries(
|
||||
self, download_service
|
||||
):
|
||||
"""Test that same episode in different series creates separate entries."""
|
||||
episodes = [EpisodeIdentifier(season=1, episode=1)]
|
||||
|
||||
ids1 = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series1",
|
||||
serie_name="Test Series 1",
|
||||
episodes=episodes,
|
||||
)
|
||||
ids2 = await download_service.add_to_queue(
|
||||
serie_id="series-2",
|
||||
serie_folder="series2",
|
||||
serie_name="Test Series 2",
|
||||
episodes=episodes,
|
||||
)
|
||||
|
||||
# Should have two separate entries (different series)
|
||||
assert len(download_service._pending_queue) == 2
|
||||
assert len(ids1) == 1
|
||||
assert len(ids2) == 1
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_multiple_episodes_with_duplicates_filters_correctly(
|
||||
self, download_service
|
||||
):
|
||||
"""Test that adding multiple episodes with some duplicates filters correctly."""
|
||||
episodes = [
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
EpisodeIdentifier(season=1, episode=2),
|
||||
EpisodeIdentifier(season=1, episode=1), # duplicate
|
||||
EpisodeIdentifier(season=1, episode=3),
|
||||
]
|
||||
|
||||
ids1 = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes,
|
||||
)
|
||||
|
||||
# Should only have 3 entries (1, 2, 3) - one filtered out
|
||||
assert len(download_service._pending_queue) == 3
|
||||
assert len(ids1) == 3
|
||||
|
||||
Reference in New Issue
Block a user