prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  News Feed task doesn't work behind proxy, impacting performance
  ### Please verify that this bug has NOT been raised before.
  
  - [X] I checked and didn't find a similar issue
  
  ### Describe the bug*
  
  The `update_news_feed` task attempts to fetch the RSS/Atom feed once daily. This, however, doesn't work behind a proxy server.
  
  The result is that these tasks occupy workers all the time, and never complete.
  Each worker is terminated roughly every 90 seconds due to this.
  
  ### Steps to Reproduce
  
  1. Put the InvenTree backend on a network unable to reach `INVENTREE_NEWS_URL`
  2. Trigger the task
  3. Task will lead to continuous timeout termination of workers
  
  ### Expected behaviour
  
  Task should finish with no new News entries added if URL is unreachable.
  
  ### Deployment Method
  
  - [ ] Docker
  - [X] Bare metal
  
  ### Version Information
  
  0.12.10
  
  ### Please verify if you can reproduce this bug on the demo site.
  
  - [ ] I can reproduce this bug on the demo site.
  
  ### Relevant log output
  
  _No response_
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `InvenTree/common/tasks.py`
  Content:
  ```
  1 """Tasks (processes that get offloaded) for common app."""
  2 
  3 import logging
  4 import os
  5 from datetime import datetime, timedelta
  6 
  7 from django.conf import settings
  8 from django.core.exceptions import AppRegistryNotReady
  9 from django.db.utils import IntegrityError, OperationalError
  10 from django.utils import timezone
  11 
  12 import feedparser
  13 
  14 from InvenTree.helpers_model import getModelsWithMixin
  15 from InvenTree.models import InvenTreeNotesMixin
  16 from InvenTree.tasks import ScheduledTask, scheduled_task
  17 
  18 logger = logging.getLogger('inventree')
  19 
  20 
  21 @scheduled_task(ScheduledTask.DAILY)
  22 def delete_old_notifications():
  23     """Remove old notifications from the database.
  24 
  25     Anything older than ~3 months is removed
  26     """
  27     try:
  28         from common.models import NotificationEntry
  29     except AppRegistryNotReady:  # pragma: no cover
  30         logger.info(
  31             "Could not perform 'delete_old_notifications' - App registry not ready"
  32         )
  33         return
  34 
  35     before = timezone.now() - timedelta(days=90)
  36 
  37     # Delete notification records before the specified date
  38     NotificationEntry.objects.filter(updated__lte=before).delete()
  39 
  40 
  41 @scheduled_task(ScheduledTask.DAILY)
  42 def update_news_feed():
  43     """Update the newsfeed."""
  44     try:
  45         from common.models import NewsFeedEntry
  46     except AppRegistryNotReady:  # pragma: no cover
  47         logger.info("Could not perform 'update_news_feed' - App registry not ready")
  48         return
  49 
  50     # Fetch and parse feed
  51     try:
  52         d = feedparser.parse(settings.INVENTREE_NEWS_URL)
  53     except Exception as entry:  # pragma: no cover
  54         logger.warning('update_news_feed: Error parsing the newsfeed', entry)
  55         return
  56 
  57     # Get a reference list
  58     id_list = [a.feed_id for a in NewsFeedEntry.objects.all()]
  59 
  60     # Iterate over entries
  61     for entry in d.entries:
  62         # Check if id already exists
  63         if entry.id in id_list:
  64             continue
  65 
  66         # Create entry
  67         try:
  68             NewsFeedEntry.objects.create(
  69                 feed_id=entry.id,
  70                 title=entry.title,
  71                 link=entry.link,
  72                 published=entry.published,
  73                 author=entry.author,
  74                 summary=entry.summary,
  75             )
  76         except (IntegrityError, OperationalError):
  77             # Sometimes errors-out on database start-up
  78             pass
  79 
  80     logger.info('update_news_feed: Sync done')
  81 
  82 
  83 @scheduled_task(ScheduledTask.DAILY)
  84 def delete_old_notes_images():
  85     """Remove old notes images from the database.
  86 
  87     Anything older than ~3 months is removed, unless it is linked to a note
  88     """
  89     try:
  90         from common.models import NotesImage
  91     except AppRegistryNotReady:
  92         logger.info(
  93             "Could not perform 'delete_old_notes_images' - App registry not ready"
  94         )
  95         return
  96 
  97     # Remove any notes which point to non-existent image files
  98     for note in NotesImage.objects.all():
  99         if not os.path.exists(note.image.path):
  100             logger.info('Deleting note %s - image file does not exist', note.image.path)
  101             note.delete()
  102 
  103     note_classes = getModelsWithMixin(InvenTreeNotesMixin)
  104     before = datetime.now() - timedelta(days=90)
  105 
  106     for note in NotesImage.objects.filter(date__lte=before):
  107         # Find any images which are no longer referenced by a note
  108 
  109         found = False
  110 
  111         img = note.image.name
  112 
  113         for model in note_classes:
  114             if model.objects.filter(notes__icontains=img).exists():
  115                 found = True
  116                 break
  117 
  118         if not found:
  119             logger.info('Deleting note %s - image file not linked to a note', img)
  120             note.delete()
  121 
  122     # Finally, remove any images in the notes dir which are not linked to a note
  123     notes_dir = os.path.join(settings.MEDIA_ROOT, 'notes')
  124 
  125     try:
  126         images = os.listdir(notes_dir)
  127     except FileNotFoundError:
  128         # Thrown if the directory does not exist
  129         images = []
  130 
  131     all_notes = NotesImage.objects.all()
  132 
  133     for image in images:
  134         found = False
  135         for note in all_notes:
  136             img_path = os.path.basename(note.image.path)
  137             if img_path == image:
  138                 found = True
  139                 break
  140 
  141         if not found:
  142             logger.info('Deleting note %s - image file not linked to a note', image)
  143             os.remove(os.path.join(notes_dir, image))
  144
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/InvenTree/common/tasks.py b/InvenTree/common/tasks.py
  --- a/InvenTree/common/tasks.py
  +++ b/InvenTree/common/tasks.py
  @@ -10,6 +10,7 @@
   from django.utils import timezone
   
   import feedparser
  +import requests
   
   from InvenTree.helpers_model import getModelsWithMixin
   from InvenTree.models import InvenTreeNotesMixin
  @@ -47,11 +48,16 @@
           logger.info("Could not perform 'update_news_feed' - App registry not ready")
           return
   
  +    # News feed isn't defined, no need to continue
  +    if not settings.INVENTREE_NEWS_URL or type(settings.INVENTREE_NEWS_URL) != str:
  +        return
  +
       # Fetch and parse feed
       try:
  -        d = feedparser.parse(settings.INVENTREE_NEWS_URL)
  -    except Exception as entry:  # pragma: no cover
  -        logger.warning('update_news_feed: Error parsing the newsfeed', entry)
  +        feed = requests.get(settings.INVENTREE_NEWS_URL)
  +        d = feedparser.parse(feed.content)
  +    except Exception:  # pragma: no cover
  +        logger.warning('update_news_feed: Error parsing the newsfeed')
           return
   
       # Get a reference list
  
verification_info: {"golden_diff": "diff --git a/InvenTree/common/tasks.py b/InvenTree/common/tasks.py\n--- a/InvenTree/common/tasks.py\n+++ b/InvenTree/common/tasks.py\n@@ -10,6 +10,7 @@\n from django.utils import timezone\n \n import feedparser\n+import requests\n \n from InvenTree.helpers_model import getModelsWithMixin\n from InvenTree.models import InvenTreeNotesMixin\n@@ -47,11 +48,16 @@\n         logger.info(\"Could not perform 'update_news_feed' - App registry not ready\")\n         return\n \n+    # News feed isn't defined, no need to continue\n+    if not settings.INVENTREE_NEWS_URL or type(settings.INVENTREE_NEWS_URL) != str:\n+        return\n+\n     # Fetch and parse feed\n     try:\n-        d = feedparser.parse(settings.INVENTREE_NEWS_URL)\n-    except Exception as entry:  # pragma: no cover\n-        logger.warning('update_news_feed: Error parsing the newsfeed', entry)\n+        feed = requests.get(settings.INVENTREE_NEWS_URL)\n+        d = feedparser.parse(feed.content)\n+    except Exception:  # pragma: no cover\n+        logger.warning('update_news_feed: Error parsing the newsfeed')\n         return\n \n     # Get a reference list\n", "issue": "News Feed task doesn't work behind proxy, impacting performance\n### Please verify that this bug has NOT been raised before.\n\n- [X] I checked and didn't find a similar issue\n\n### Describe the bug*\n\nThe `update_news_feed` task attempts to fetch the RSS/Atom feed once daily. This, however, doesn't work behind a proxy server.\r\n\r\nThe result is that these tasks occupy workers all the time, and never complete.\r\nEach worker is terminated roughly every 90 seconds due to this.\n\n### Steps to Reproduce\n\n1. Put the InvenTree backend on a network unable to reach `INVENTREE_NEWS_URL`\r\n2. Trigger the task\r\n3. Task will lead to continuous timeout termination of workers\n\n### Expected behaviour\n\nTask should finish with no new News entries added if URL is unreachable.\n\n### Deployment Method\n\n- [ ] Docker\n- [X] Bare metal\n\n### Version Information\n\n0.12.10\n\n### Please verify if you can reproduce this bug on the demo site.\n\n- [ ] I can reproduce this bug on the demo site.\n\n### Relevant log output\n\n_No response_\n", "before_files": [{"content": "\"\"\"Tasks (processes that get offloaded) for common app.\"\"\"\n\nimport logging\nimport os\nfrom datetime import datetime, timedelta\n\nfrom django.conf import settings\nfrom django.core.exceptions import AppRegistryNotReady\nfrom django.db.utils import IntegrityError, OperationalError\nfrom django.utils import timezone\n\nimport feedparser\n\nfrom InvenTree.helpers_model import getModelsWithMixin\nfrom InvenTree.models import InvenTreeNotesMixin\nfrom InvenTree.tasks import ScheduledTask, scheduled_task\n\nlogger = logging.getLogger('inventree')\n\n\n@scheduled_task(ScheduledTask.DAILY)\ndef delete_old_notifications():\n    \"\"\"Remove old notifications from the database.\n\n    Anything older than ~3 months is removed\n    \"\"\"\n    try:\n        from common.models import NotificationEntry\n    except AppRegistryNotReady:  # pragma: no cover\n        logger.info(\n            \"Could not perform 'delete_old_notifications' - App registry not ready\"\n        )\n        return\n\n    before = timezone.now() - timedelta(days=90)\n\n    # Delete notification records before the specified date\n    NotificationEntry.objects.filter(updated__lte=before).delete()\n\n\n@scheduled_task(ScheduledTask.DAILY)\ndef update_news_feed():\n    \"\"\"Update the newsfeed.\"\"\"\n    try:\n        from common.models import NewsFeedEntry\n    except AppRegistryNotReady:  # pragma: no cover\n        logger.info(\"Could not perform 'update_news_feed' - App registry not ready\")\n        return\n\n    # Fetch and parse feed\n    try:\n        d = feedparser.parse(settings.INVENTREE_NEWS_URL)\n    except Exception as entry:  # pragma: no cover\n        logger.warning('update_news_feed: Error parsing the newsfeed', entry)\n        return\n\n    # Get a reference list\n    id_list = [a.feed_id for a in NewsFeedEntry.objects.all()]\n\n    # Iterate over entries\n    for entry in d.entries:\n        # Check if id already exists\n        if entry.id in id_list:\n            continue\n\n        # Create entry\n        try:\n            NewsFeedEntry.objects.create(\n                feed_id=entry.id,\n                title=entry.title,\n                link=entry.link,\n                published=entry.published,\n                author=entry.author,\n                summary=entry.summary,\n            )\n        except (IntegrityError, OperationalError):\n            # Sometimes errors-out on database start-up\n            pass\n\n    logger.info('update_news_feed: Sync done')\n\n\n@scheduled_task(ScheduledTask.DAILY)\ndef delete_old_notes_images():\n    \"\"\"Remove old notes images from the database.\n\n    Anything older than ~3 months is removed, unless it is linked to a note\n    \"\"\"\n    try:\n        from common.models import NotesImage\n    except AppRegistryNotReady:\n        logger.info(\n            \"Could not perform 'delete_old_notes_images' - App registry not ready\"\n        )\n        return\n\n    # Remove any notes which point to non-existent image files\n    for note in NotesImage.objects.all():\n        if not os.path.exists(note.image.path):\n            logger.info('Deleting note %s - image file does not exist', note.image.path)\n            note.delete()\n\n    note_classes = getModelsWithMixin(InvenTreeNotesMixin)\n    before = datetime.now() - timedelta(days=90)\n\n    for note in NotesImage.objects.filter(date__lte=before):\n        # Find any images which are no longer referenced by a note\n\n        found = False\n\n        img = note.image.name\n\n        for model in note_classes:\n            if model.objects.filter(notes__icontains=img).exists():\n                found = True\n                break\n\n        if not found:\n            logger.info('Deleting note %s - image file not linked to a note', img)\n            note.delete()\n\n    # Finally, remove any images in the notes dir which are not linked to a note\n    notes_dir = os.path.join(settings.MEDIA_ROOT, 'notes')\n\n    try:\n        images = os.listdir(notes_dir)\n    except FileNotFoundError:\n        # Thrown if the directory does not exist\n        images = []\n\n    all_notes = NotesImage.objects.all()\n\n    for image in images:\n        found = False\n        for note in all_notes:\n            img_path = os.path.basename(note.image.path)\n            if img_path == image:\n                found = True\n                break\n\n        if not found:\n            logger.info('Deleting note %s - image file not linked to a note', image)\n            os.remove(os.path.join(notes_dir, image))\n", "path": "InvenTree/common/tasks.py"}], "after_files": [{"content": "\"\"\"Tasks (processes that get offloaded) for common app.\"\"\"\n\nimport logging\nimport os\nfrom datetime import datetime, timedelta\n\nfrom django.conf import settings\nfrom django.core.exceptions import AppRegistryNotReady\nfrom django.db.utils import IntegrityError, OperationalError\nfrom django.utils import timezone\n\nimport feedparser\nimport requests\n\nfrom InvenTree.helpers_model import getModelsWithMixin\nfrom InvenTree.models import InvenTreeNotesMixin\nfrom InvenTree.tasks import ScheduledTask, scheduled_task\n\nlogger = logging.getLogger('inventree')\n\n\n@scheduled_task(ScheduledTask.DAILY)\ndef delete_old_notifications():\n    \"\"\"Remove old notifications from the database.\n\n    Anything older than ~3 months is removed\n    \"\"\"\n    try:\n        from common.models import NotificationEntry\n    except AppRegistryNotReady:  # pragma: no cover\n        logger.info(\n            \"Could not perform 'delete_old_notifications' - App registry not ready\"\n        )\n        return\n\n    before = timezone.now() - timedelta(days=90)\n\n    # Delete notification records before the specified date\n    NotificationEntry.objects.filter(updated__lte=before).delete()\n\n\n@scheduled_task(ScheduledTask.DAILY)\ndef update_news_feed():\n    \"\"\"Update the newsfeed.\"\"\"\n    try:\n        from common.models import NewsFeedEntry\n    except AppRegistryNotReady:  # pragma: no cover\n        logger.info(\"Could not perform 'update_news_feed' - App registry not ready\")\n        return\n\n    # News feed isn't defined, no need to continue\n    if not settings.INVENTREE_NEWS_URL or type(settings.INVENTREE_NEWS_URL) != str:\n        return\n\n    # Fetch and parse feed\n    try:\n        feed = requests.get(settings.INVENTREE_NEWS_URL)\n        d = feedparser.parse(feed.content)\n    except Exception:  # pragma: no cover\n        logger.warning('update_news_feed: Error parsing the newsfeed')\n        return\n\n    # Get a reference list\n    id_list = [a.feed_id for a in NewsFeedEntry.objects.all()]\n\n    # Iterate over entries\n    for entry in d.entries:\n        # Check if id already exists\n        if entry.id in id_list:\n            continue\n\n        # Create entry\n        try:\n            NewsFeedEntry.objects.create(\n                feed_id=entry.id,\n                title=entry.title,\n                link=entry.link,\n                published=entry.published,\n                author=entry.author,\n                summary=entry.summary,\n            )\n        except (IntegrityError, OperationalError):\n            # Sometimes errors-out on database start-up\n            pass\n\n    logger.info('update_news_feed: Sync done')\n\n\n@scheduled_task(ScheduledTask.DAILY)\ndef delete_old_notes_images():\n    \"\"\"Remove old notes images from the database.\n\n    Anything older than ~3 months is removed, unless it is linked to a note\n    \"\"\"\n    try:\n        from common.models import NotesImage\n    except AppRegistryNotReady:\n        logger.info(\n            \"Could not perform 'delete_old_notes_images' - App registry not ready\"\n        )\n        return\n\n    # Remove any notes which point to non-existent image files\n    for note in NotesImage.objects.all():\n        if not os.path.exists(note.image.path):\n            logger.info('Deleting note %s - image file does not exist', note.image.path)\n            note.delete()\n\n    note_classes = getModelsWithMixin(InvenTreeNotesMixin)\n    before = datetime.now() - timedelta(days=90)\n\n    for note in NotesImage.objects.filter(date__lte=before):\n        # Find any images which are no longer referenced by a note\n\n        found = False\n\n        img = note.image.name\n\n        for model in note_classes:\n            if model.objects.filter(notes__icontains=img).exists():\n                found = True\n                break\n\n        if not found:\n            logger.info('Deleting note %s - image file not linked to a note', img)\n            note.delete()\n\n    # Finally, remove any images in the notes dir which are not linked to a note\n    notes_dir = os.path.join(settings.MEDIA_ROOT, 'notes')\n\n    try:\n        images = os.listdir(notes_dir)\n    except FileNotFoundError:\n        # Thrown if the directory does not exist\n        images = []\n\n    all_notes = NotesImage.objects.all()\n\n    for image in images:\n        found = False\n        for note in all_notes:\n            img_path = os.path.basename(note.image.path)\n            if img_path == image:\n                found = True\n                break\n\n        if not found:\n            logger.info('Deleting note %s - image file not linked to a note', image)\n            os.remove(os.path.join(notes_dir, image))\n", "path": "InvenTree/common/tasks.py"}]}