prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Create Freq Capping Goals for Jobs
  Create Global Frequency Capping goals for Jobs (introduced in #1034). 
  
  Goals:
   - Total impressions
   - Total clicks and button clicks (combined)
   - Total blocks
  
  A `Job` can have multiple goals (freq capping, datetime), first one reached will un-publish the `Job`.
  
  Requires #1036. Also `Job`s with Freq Cap goals must get data from Redash more often (TBD).
  
  ## Use case:
   - Publish a Snippet for 1M impressions. It's fine it snippet gets 5K-10K impressions more.
  
  
  ## Questions
   - [x] How do we handle Jobs with Freq Capping when no Telemetry data is available? 
     - Jobs that have impression, block or click limits set and no metrics data updated for at least 24 hours will be marked Complete.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `snippets/base/management/commands/update_jobs.py`
  Content:
  ```
  1 from datetime import datetime
  2 
  3 from django.contrib.auth import get_user_model
  4 from django.core.management.base import BaseCommand
  5 from django.db import transaction
  6 from django.db.models import F, Q
  7 
  8 from snippets.base.models import Job
  9 
  10 
  11 class Command(BaseCommand):
  12     args = "(no args)"
  13     help = "Update Jobs"
  14 
  15     @transaction.atomic
  16     def handle(self, *args, **options):
  17         now = datetime.utcnow()
  18         user = get_user_model().objects.get_or_create(username='snippets_bot')[0]
  19         count_total_completed = 0
  20 
  21         # Publish Scheduled Jobs with `publish_start` before now or without
  22         # publish_start.
  23         jobs = Job.objects.filter(status=Job.SCHEDULED).filter(
  24             Q(publish_start__lte=now) | Q(publish_start=None)
  25         )
  26         count_published = jobs.count()
  27         for job in jobs:
  28             job.change_status(
  29                 status=Job.PUBLISHED,
  30                 user=user,
  31                 reason='Published start date reached.',
  32             )
  33 
  34         # Disable Published Jobs with `publish_end` before now.
  35         jobs = Job.objects.filter(status=Job.PUBLISHED, publish_end__lte=now)
  36         count_publication_end = jobs.count()
  37         count_total_completed += count_publication_end
  38 
  39         for job in jobs:
  40             job.change_status(
  41                 status=Job.COMPLETED,
  42                 user=user,
  43                 reason='Publication end date reached.',
  44             )
  45 
  46         # Disable Jobs that reached Impression, Click or Block limits.
  47         count_limit = {}
  48         for limit in ['impressions', 'clicks', 'blocks']:
  49             jobs = (Job.objects
  50                     .filter(status=Job.PUBLISHED)
  51                     .exclude(**{f'limit_{limit}': 0})
  52                     .filter(**{f'limit_{limit}__lte': F(f'metric_{limit}')}))
  53             for job in jobs:
  54                 job.change_status(
  55                     status=Job.COMPLETED,
  56                     user=user,
  57                     reason=f'Limit reached: {limit}.',
  58                 )
  59 
  60             count_limit[limit] = jobs.count()
  61             count_total_completed += count_limit[limit]
  62 
  63         count_running = Job.objects.filter(status=Job.PUBLISHED).count()
  64 
  65         self.stdout.write(
  66             f'Jobs Published: {count_published}\n'
  67             f'Jobs Completed: {count_total_completed}\n'
  68             f'  - Reached Publication End Date: {count_publication_end}\n'
  69             f'  - Reached Impressions Limit: {count_limit["impressions"]}\n'
  70             f'  - Reached Clicks Limit: {count_limit["clicks"]}\n'
  71             f'  - Reached Blocks Limit: {count_limit["blocks"]}\n'
  72             f'Total Jobs Running: {count_running}\n'
  73         )
  74
  ```
  --- 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/snippets/base/management/commands/update_jobs.py b/snippets/base/management/commands/update_jobs.py
  --- a/snippets/base/management/commands/update_jobs.py
  +++ b/snippets/base/management/commands/update_jobs.py
  @@ -1,4 +1,4 @@
  -from datetime import datetime
  +from datetime import datetime, timedelta
   
   from django.contrib.auth import get_user_model
   from django.core.management.base import BaseCommand
  @@ -60,6 +60,23 @@
               count_limit[limit] = jobs.count()
               count_total_completed += count_limit[limit]
   
  +        # Disable Jobs that have Impression, Click or Block limits but don't
  +        # have metrics data for at least 24h. This is to handle cases where the
  +        # Metrics Pipeline is broken.
  +        yesterday = datetime.utcnow() - timedelta(days=1)
  +        jobs = (Job.objects
  +                .filter(status=Job.PUBLISHED)
  +                .exclude(limit_impressions=0, limit_clicks=0, limit_blocks=0)
  +                .filter(metric_last_update__lt=yesterday))
  +        for job in jobs:
  +            job.change_status(
  +                status=Job.COMPLETED,
  +                user=user,
  +                reason=f'Premature termination due to missing metrics.',
  +            )
  +        count_premature_termination = jobs.count()
  +        count_total_completed += count_premature_termination
  +
           count_running = Job.objects.filter(status=Job.PUBLISHED).count()
   
           self.stdout.write(
  @@ -69,5 +86,6 @@
               f'  - Reached Impressions Limit: {count_limit["impressions"]}\n'
               f'  - Reached Clicks Limit: {count_limit["clicks"]}\n'
               f'  - Reached Blocks Limit: {count_limit["blocks"]}\n'
  +            f'  - Premature Termination due to missing metrics: {count_premature_termination}\n'
               f'Total Jobs Running: {count_running}\n'
           )
  
verification_info: {"golden_diff": "diff --git a/snippets/base/management/commands/update_jobs.py b/snippets/base/management/commands/update_jobs.py\n--- a/snippets/base/management/commands/update_jobs.py\n+++ b/snippets/base/management/commands/update_jobs.py\n@@ -1,4 +1,4 @@\n-from datetime import datetime\n+from datetime import datetime, timedelta\n \n from django.contrib.auth import get_user_model\n from django.core.management.base import BaseCommand\n@@ -60,6 +60,23 @@\n             count_limit[limit] = jobs.count()\n             count_total_completed += count_limit[limit]\n \n+        # Disable Jobs that have Impression, Click or Block limits but don't\n+        # have metrics data for at least 24h. This is to handle cases where the\n+        # Metrics Pipeline is broken.\n+        yesterday = datetime.utcnow() - timedelta(days=1)\n+        jobs = (Job.objects\n+                .filter(status=Job.PUBLISHED)\n+                .exclude(limit_impressions=0, limit_clicks=0, limit_blocks=0)\n+                .filter(metric_last_update__lt=yesterday))\n+        for job in jobs:\n+            job.change_status(\n+                status=Job.COMPLETED,\n+                user=user,\n+                reason=f'Premature termination due to missing metrics.',\n+            )\n+        count_premature_termination = jobs.count()\n+        count_total_completed += count_premature_termination\n+\n         count_running = Job.objects.filter(status=Job.PUBLISHED).count()\n \n         self.stdout.write(\n@@ -69,5 +86,6 @@\n             f'  - Reached Impressions Limit: {count_limit[\"impressions\"]}\\n'\n             f'  - Reached Clicks Limit: {count_limit[\"clicks\"]}\\n'\n             f'  - Reached Blocks Limit: {count_limit[\"blocks\"]}\\n'\n+            f'  - Premature Termination due to missing metrics: {count_premature_termination}\\n'\n             f'Total Jobs Running: {count_running}\\n'\n         )\n", "issue": "Create Freq Capping Goals for Jobs\nCreate Global Frequency Capping goals for Jobs (introduced in #1034). \r\n\r\nGoals:\r\n - Total impressions\r\n - Total clicks and button clicks (combined)\r\n - Total blocks\r\n\r\nA `Job` can have multiple goals (freq capping, datetime), first one reached will un-publish the `Job`.\r\n\r\nRequires #1036. Also `Job`s with Freq Cap goals must get data from Redash more often (TBD).\r\n\r\n## Use case:\r\n - Publish a Snippet for 1M impressions. It's fine it snippet gets 5K-10K impressions more.\r\n\r\n\r\n## Questions\r\n - [x] How do we handle Jobs with Freq Capping when no Telemetry data is available? \r\n   - Jobs that have impression, block or click limits set and no metrics data updated for at least 24 hours will be marked Complete.\n", "before_files": [{"content": "from datetime import datetime\n\nfrom django.contrib.auth import get_user_model\nfrom django.core.management.base import BaseCommand\nfrom django.db import transaction\nfrom django.db.models import F, Q\n\nfrom snippets.base.models import Job\n\n\nclass Command(BaseCommand):\n    args = \"(no args)\"\n    help = \"Update Jobs\"\n\n    @transaction.atomic\n    def handle(self, *args, **options):\n        now = datetime.utcnow()\n        user = get_user_model().objects.get_or_create(username='snippets_bot')[0]\n        count_total_completed = 0\n\n        # Publish Scheduled Jobs with `publish_start` before now or without\n        # publish_start.\n        jobs = Job.objects.filter(status=Job.SCHEDULED).filter(\n            Q(publish_start__lte=now) | Q(publish_start=None)\n        )\n        count_published = jobs.count()\n        for job in jobs:\n            job.change_status(\n                status=Job.PUBLISHED,\n                user=user,\n                reason='Published start date reached.',\n            )\n\n        # Disable Published Jobs with `publish_end` before now.\n        jobs = Job.objects.filter(status=Job.PUBLISHED, publish_end__lte=now)\n        count_publication_end = jobs.count()\n        count_total_completed += count_publication_end\n\n        for job in jobs:\n            job.change_status(\n                status=Job.COMPLETED,\n                user=user,\n                reason='Publication end date reached.',\n            )\n\n        # Disable Jobs that reached Impression, Click or Block limits.\n        count_limit = {}\n        for limit in ['impressions', 'clicks', 'blocks']:\n            jobs = (Job.objects\n                    .filter(status=Job.PUBLISHED)\n                    .exclude(**{f'limit_{limit}': 0})\n                    .filter(**{f'limit_{limit}__lte': F(f'metric_{limit}')}))\n            for job in jobs:\n                job.change_status(\n                    status=Job.COMPLETED,\n                    user=user,\n                    reason=f'Limit reached: {limit}.',\n                )\n\n            count_limit[limit] = jobs.count()\n            count_total_completed += count_limit[limit]\n\n        count_running = Job.objects.filter(status=Job.PUBLISHED).count()\n\n        self.stdout.write(\n            f'Jobs Published: {count_published}\\n'\n            f'Jobs Completed: {count_total_completed}\\n'\n            f'  - Reached Publication End Date: {count_publication_end}\\n'\n            f'  - Reached Impressions Limit: {count_limit[\"impressions\"]}\\n'\n            f'  - Reached Clicks Limit: {count_limit[\"clicks\"]}\\n'\n            f'  - Reached Blocks Limit: {count_limit[\"blocks\"]}\\n'\n            f'Total Jobs Running: {count_running}\\n'\n        )\n", "path": "snippets/base/management/commands/update_jobs.py"}], "after_files": [{"content": "from datetime import datetime, timedelta\n\nfrom django.contrib.auth import get_user_model\nfrom django.core.management.base import BaseCommand\nfrom django.db import transaction\nfrom django.db.models import F, Q\n\nfrom snippets.base.models import Job\n\n\nclass Command(BaseCommand):\n    args = \"(no args)\"\n    help = \"Update Jobs\"\n\n    @transaction.atomic\n    def handle(self, *args, **options):\n        now = datetime.utcnow()\n        user = get_user_model().objects.get_or_create(username='snippets_bot')[0]\n        count_total_completed = 0\n\n        # Publish Scheduled Jobs with `publish_start` before now or without\n        # publish_start.\n        jobs = Job.objects.filter(status=Job.SCHEDULED).filter(\n            Q(publish_start__lte=now) | Q(publish_start=None)\n        )\n        count_published = jobs.count()\n        for job in jobs:\n            job.change_status(\n                status=Job.PUBLISHED,\n                user=user,\n                reason='Published start date reached.',\n            )\n\n        # Disable Published Jobs with `publish_end` before now.\n        jobs = Job.objects.filter(status=Job.PUBLISHED, publish_end__lte=now)\n        count_publication_end = jobs.count()\n        count_total_completed += count_publication_end\n\n        for job in jobs:\n            job.change_status(\n                status=Job.COMPLETED,\n                user=user,\n                reason='Publication end date reached.',\n            )\n\n        # Disable Jobs that reached Impression, Click or Block limits.\n        count_limit = {}\n        for limit in ['impressions', 'clicks', 'blocks']:\n            jobs = (Job.objects\n                    .filter(status=Job.PUBLISHED)\n                    .exclude(**{f'limit_{limit}': 0})\n                    .filter(**{f'limit_{limit}__lte': F(f'metric_{limit}')}))\n            for job in jobs:\n                job.change_status(\n                    status=Job.COMPLETED,\n                    user=user,\n                    reason=f'Limit reached: {limit}.',\n                )\n\n            count_limit[limit] = jobs.count()\n            count_total_completed += count_limit[limit]\n\n        # Disable Jobs that have Impression, Click or Block limits but don't\n        # have metrics data for at least 24h. This is to handle cases where the\n        # Metrics Pipeline is broken.\n        yesterday = datetime.utcnow() - timedelta(days=1)\n        jobs = (Job.objects\n                .filter(status=Job.PUBLISHED)\n                .exclude(limit_impressions=0, limit_clicks=0, limit_blocks=0)\n                .filter(metric_last_update__lt=yesterday))\n        for job in jobs:\n            job.change_status(\n                status=Job.COMPLETED,\n                user=user,\n                reason=f'Premature termination due to missing metrics.',\n            )\n        count_premature_termination = jobs.count()\n        count_total_completed += count_premature_termination\n\n        count_running = Job.objects.filter(status=Job.PUBLISHED).count()\n\n        self.stdout.write(\n            f'Jobs Published: {count_published}\\n'\n            f'Jobs Completed: {count_total_completed}\\n'\n            f'  - Reached Publication End Date: {count_publication_end}\\n'\n            f'  - Reached Impressions Limit: {count_limit[\"impressions\"]}\\n'\n            f'  - Reached Clicks Limit: {count_limit[\"clicks\"]}\\n'\n            f'  - Reached Blocks Limit: {count_limit[\"blocks\"]}\\n'\n            f'  - Premature Termination due to missing metrics: {count_premature_termination}\\n'\n            f'Total Jobs Running: {count_running}\\n'\n        )\n", "path": "snippets/base/management/commands/update_jobs.py"}]}