Repository: Flexget/Flexget

Issue:
Series title parsing failure causes huge amount of discover queries
Following situation creates hundreds of discover queries when trying to find "missing" episodes between 14-264

- S01E01    |345d 1h  |[FlexGet] SeriesName - S01E01 [1080p][HEVC x265 10bit][Multi-Subs] (Weekly) *              |1080p h265 10bit|      
- S01E013    |345d 1h  |[FlexGet] SeriesName - S01E01 [1080p][HEVC x265 10bit][Multi-Subs] (Weekly) *              |1080p h265 10bit|      
- S01E265   |302d 23h |[FlexGet] SeriesName (Season 01) [1080p][HEVC x265 10bit][Dual-Audio][Multi-Subs] (Batch) *|1080p h265 10bit|
 
Stems from the fact that x265 is identified as S01E265


Discussion:
Hmm, I just tested those titles, and they were identified as S01E01 and S01, which seem correct. Do you know what else might cause it to go wrong in your situation?
I thought maybe I had figured out the answer with #4243, but I just misunderstood your output, thinking that second quality instance was part of the title rather than part of the series cli output.
I guess we could put a max on the number of 'missing' eps? But would it be hard coded or configurable? Should it prevent any searching at all due to thinking it's an error, or just limit it to the cap?
What do you think of that solution? I'd also like to figure out what went wrong with the parsing, but I can't replicate.



Patch:
diff --git a/flexget/components/series/next_series_episodes.py b/flexget/components/series/next_series_episodes.py
index 1afefed083..6a50609b43 100644
--- a/flexget/components/series/next_series_episodes.py
+++ b/flexget/components/series/next_series_episodes.py
@@ -13,6 +13,8 @@
 
 logger = logger.bind(name='next_series_episodes')
 
+BACKFILL_LIMIT_DEFAULT = 25
+
 
 class NextSeriesEpisodes:
     """Emit next episode number from all series configured in this task.
@@ -28,6 +30,12 @@ class NextSeriesEpisodes:
                 'properties': {
                     'from_start': {'type': 'boolean', 'default': False},
                     'backfill': {'type': 'boolean', 'default': False},
+                    'backfill_limit': {
+                        'type': 'integer',
+                        'default': BACKFILL_LIMIT_DEFAULT,
+                        'description': 'If the gap between episodes is larger than this limit, '
+                        'they will not be emitted.',
+                    },
                     'only_same_season': {'type': 'boolean', 'default': False},
                 },
                 'additionalProperties': False,
@@ -87,6 +95,7 @@ def on_task_input(self, task, config):
             return None
         if isinstance(config, bool):
             config = {}
+        config.setdefault('backfill_limit', BACKFILL_LIMIT_DEFAULT)
         self.config = config
         if task.is_rerun:
             # Just return calculated next eps on reruns
@@ -190,10 +199,17 @@ def on_task_input(self, task, config):
                             for ep in downloaded_this_season:
                                 with contextlib.suppress(ValueError):
                                     eps_to_get.remove(ep.number)
-                            entries.extend(
-                                self.search_entry(series, season, x, task, rerun=False)
-                                for x in eps_to_get
-                            )
+                            if len(eps_to_get) > config['backfill_limit']:
+                                logger.warning(
+                                    'Series {} has more than 50 episodes to backfill. Assuming this is an '
+                                    'error and not searching for them.',
+                                    series.name,
+                                )
+                            else:
+                                entries.extend(
+                                    self.search_entry(series, season, x, task, rerun=False)
+                                    for x in eps_to_get
+                                )
                             # If we have already downloaded the latest known episode, try the next episode
                             if latest_ep_this_season.releases:
                                 entries.append(


Test patch:
diff --git a/flexget/tests/test_next_series_episodes.py b/flexget/tests/test_next_series_episodes.py
index 083da7b0ac..6307bb290b 100644
--- a/flexget/tests/test_next_series_episodes.py
+++ b/flexget/tests/test_next_series_episodes.py
@@ -35,6 +35,14 @@ class TestNextSeriesEpisodes:
             series:
             - Test Series 1
             max_reruns: 0
+          test_next_series_episodes_backfill_limit:
+            next_series_episodes:
+              backfill: yes
+              backfill_limit: 10
+            series:
+            - Test Series 1:
+                identified_by: ep
+            max_reruns: 0
           test_next_series_episodes_rejected:
             next_series_episodes:
               backfill: yes
@@ -154,6 +162,15 @@ def test_next_series_episodes_no_backfill(self, execute_task):
         assert len(task.all_entries) == 1
         assert task.find_entry(title='Test Series 1 S01E06')
 
+    def test_next_series_episodes_backfill_limit(self, execute_task):
+        self.inject_series(execute_task, 'Test Series 1 S01E01')
+        self.inject_series(execute_task, 'Test Series 1 S01E13')
+        task = execute_task('test_next_series_episodes_backfill_limit')
+        assert len(task.all_entries) == 1, "missing episodes over limit. Should not backfill"
+        self.inject_series(execute_task, 'Test Series 1 S01E12')
+        task = execute_task('test_next_series_episodes_backfill_limit')
+        assert len(task.all_entries) == 11, "missing episodes less than limit. Should backfill"
+
     def test_next_series_episodes_rejected(self, execute_task):
         self.inject_series(execute_task, 'Test Series 2 S01E03 720p')
         task = execute_task('test_next_series_episodes_rejected')