prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Make SiteDriver a context manager
  It will provide convenient api to manage selenium resources and properly shout down selenium driver.   
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `shopelectro/tasks.py`
  Content:
  ```
  1 from contextlib import contextmanager
  2 
  3 from django.conf import settings
  4 from django.core.management import call_command
  5 from selenium.common.exceptions import WebDriverException
  6 
  7 from shopelectro import selenium
  8 from shopelectro.celery import app
  9 from shopelectro.report import TelegramReport
  10 from shopelectro.models import CategoryPage
  11 from shopelectro.management.commands._update_catalog import utils
  12 
  13 
  14 @contextmanager
  15 def report():
  16     try:
  17         yield
  18     except Exception as error:
  19         utils.report(str(error))
  20         raise error
  21 
  22 
  23 @app.task
  24 def generate_price_files():
  25     with report():
  26         call_command('price')
  27         print('Generate prices complete.')
  28 
  29 
  30 @app.task
  31 def generate_excel_file():
  32     with report():
  33         call_command('excel')
  34         print('Generate excel complete.')
  35 
  36 
  37 @app.task
  38 def collect_static():
  39     with report():
  40         call_command('collectstatic', '--noinput')
  41 
  42 
  43 @app.task
  44 def update_catalog_command():
  45     with report():
  46         call_command('update_catalog')
  47 
  48 
  49 @app.task
  50 def update_default_templates():
  51     with report():
  52         call_command('update_default_templates')
  53 
  54 
  55 @app.task(autoretry_for=(Exception,), max_retries=3, default_retry_delay=60*10)  # Ignore PycodestyleBear (E226)
  56 def update_catalog():
  57     # http://docs.celeryproject.org/en/latest/userguide/canvas.html#map-starmap
  58     return [
  59         update_catalog_command(),
  60         update_default_templates(),
  61         generate_price_files(),
  62         generate_excel_file(),
  63         collect_static()
  64     ]
  65 
  66 # @todo #690:30m Schedule check_purchase in the celery beat.
  67 
  68 
  69 @app.task(
  70     bind=True,
  71     autoretry_for=(WebDriverException, AssertionError),
  72     retry_kwargs={'max_retries': settings.CHECK_PURCHASE_RETRIES},
  73 )
  74 def check_purchase(self):
  75     try:
  76         driver = selenium.SiteDriver(site_url=settings.BASE_URL)
  77         category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)
  78         category_page.load()
  79         category_page.add_to_cart()
  80 
  81         order_page = selenium.OrderPage(driver)
  82         order_page.load()
  83         order_page.fill_contacts()
  84         order_page.make_order()
  85 
  86         success_page = selenium.SuccessPage(driver)
  87         assert success_page.is_success()
  88     except (WebDriverException, AssertionError) as err:
  89         if self.request.retries + 1 > self.max_retries:
  90             # report on the last attempt
  91             TelegramReport().send(f'Can\'t buy a product. Got the error: {err}')
  92         raise err
  93
  ```
  
  Path: `shopelectro/selenium/driver.py`
  Content:
  ```
  1 from urllib.parse import urljoin
  2 
  3 from django.conf import settings
  4 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
  5 from selenium.webdriver.support.ui import WebDriverWait
  6 from seleniumrequests import Remote
  7 
  8 
  9 class SiteDriver(Remote):
  10     """Provide convenient access to the site."""
  11 
  12     def __init__(self, *, site_url, **kwargs):
  13         kwargs.setdefault('command_executor', settings.SELENIUM_URL)
  14         kwargs.setdefault('desired_capabilities', DesiredCapabilities.CHROME)
  15         super().__init__(**kwargs)
  16 
  17         self.site_url = site_url
  18         self.wait = WebDriverWait(self, settings.SELENIUM_WAIT_SECONDS)
  19 
  20     def get(self, url):
  21         super().get(urljoin(self.site_url, url))
  22
  ```
  
  Path: `shopelectro/celery.py`
  Content:
  ```
  1 from __future__ import absolute_import, unicode_literals
  2 from datetime import timedelta
  3 import os
  4 
  5 from celery import Celery
  6 from kombu import Exchange, Queue
  7 
  8 # set the default Django settings module for the 'celery' program.
  9 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shopelectro.settings.local')
  10 
  11 app = Celery('shopelectro')
  12 
  13 # Exchanges
  14 default_exchange = Exchange('default', type='direct')
  15 utils_exchange = Exchange('utils', type='direct')
  16 
  17 # http://docs.celeryproject.org/en/latest/userguide/tasks.html
  18 task_queues = (
  19     Queue(
  20         name='default',
  21         exchange=default_exchange,
  22         routing_key='default',
  23     ),
  24     Queue(
  25         name='mail',
  26         exchange=utils_exchange,
  27         routing_key='utils.mail',
  28     ),
  29     Queue(
  30         name='command',
  31         exchange=utils_exchange,
  32         routing_key='utils.command',
  33     )
  34 )
  35 
  36 # http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html
  37 beat_schedule = {
  38     'update-catalog': {
  39         'task': 'shopelectro.tasks.update_catalog',
  40         'schedule': timedelta(hours=2),
  41     },
  42 }
  43 
  44 # http://docs.celeryproject.org/en/master/userguide/routing.html
  45 task_routes = {
  46     'shopelectro.tasks.update_catalog': {
  47         'queue': 'command',
  48         'routing_key': 'utils.command',
  49         'priority': 30,
  50     },
  51     'ecommerce.tasks.send_mail': {
  52         'queue': 'mail',
  53         'routing_key': 'utils.mail',
  54         'priority': 50,
  55     },
  56 }
  57 
  58 # Using a string here means the worker don't have to serialize
  59 # the configuration object to child processes.
  60 # - namespace='CELERY' means all celery-related configuration keys
  61 #   should have a `CELERY_` prefix.
  62 app.config_from_object('django.conf:settings', namespace='CELERY')
  63 
  64 # http://docs.celeryproject.org/en/latest/userguide/configuration.html
  65 
  66 BROCKER_URL = (
  67     f'amqp://{os.environ["RABBITMQ_DEFAULT_USER"]}:{os.environ["RABBITMQ_DEFAULT_PASS"]}'
  68     f'@{os.environ["RABBITMQ_URL"]}:{os.environ["RABBITMQ_PORT"]}/'
  69 )
  70 app.conf.update(
  71     broker_url=BROCKER_URL,
  72     broker_heartbeat=30,
  73     task_acks_late=True,
  74     task_default_queue='default',
  75     task_default_exchange='default',
  76     task_default_routing_key='default',
  77     task_ignore_result=True,
  78     worker_pool_restarts=1000,
  79     task_routes=task_routes,
  80     task_queues=task_queues,
  81     beat_schedule=beat_schedule,
  82 )
  83 
  84 # Load task modules from all registered Django app configs.
  85 app.autodiscover_tasks()
  86
  ```
  --- 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/shopelectro/celery.py b/shopelectro/celery.py
  --- a/shopelectro/celery.py
  +++ b/shopelectro/celery.py
  @@ -37,7 +37,11 @@
   beat_schedule = {
       'update-catalog': {
           'task': 'shopelectro.tasks.update_catalog',
  -        'schedule': timedelta(hours=2),
  +        'schedule': timedelta(hours=2).total_seconds(),
  +    },
  +    'check-purchase': {
  +        'task': 'shopelectro.tasks.check_purchase',
  +        'schedule': timedelta(days=1).total_seconds(),
       },
   }
   
  @@ -48,6 +52,11 @@
           'routing_key': 'utils.command',
           'priority': 30,
       },
  +    'shopelectro.tasks.check_purchase': {
  +        'queue': 'command',
  +        'routing_key': 'utils.command',
  +        'priority': 20,
  +    },
       'ecommerce.tasks.send_mail': {
           'queue': 'mail',
           'routing_key': 'utils.mail',
  diff --git a/shopelectro/selenium/driver.py b/shopelectro/selenium/driver.py
  --- a/shopelectro/selenium/driver.py
  +++ b/shopelectro/selenium/driver.py
  @@ -17,5 +17,11 @@
           self.site_url = site_url
           self.wait = WebDriverWait(self, settings.SELENIUM_WAIT_SECONDS)
   
  +    def __enter__(self):
  +        return self
  +
  +    def __exit__(self, *args, **kwargs):
  +        self.quit()
  +
       def get(self, url):
           super().get(urljoin(self.site_url, url))
  diff --git a/shopelectro/tasks.py b/shopelectro/tasks.py
  --- a/shopelectro/tasks.py
  +++ b/shopelectro/tasks.py
  @@ -63,8 +63,6 @@
           collect_static()
       ]
   
  -# @todo #690:30m Schedule check_purchase in the celery beat.
  -
   
   @app.task(
       bind=True,
  @@ -73,18 +71,18 @@
   )
   def check_purchase(self):
       try:
  -        driver = selenium.SiteDriver(site_url=settings.BASE_URL)
  -        category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)
  -        category_page.load()
  -        category_page.add_to_cart()
  -
  -        order_page = selenium.OrderPage(driver)
  -        order_page.load()
  -        order_page.fill_contacts()
  -        order_page.make_order()
  -
  -        success_page = selenium.SuccessPage(driver)
  -        assert success_page.is_success()
  +        with selenium.SiteDriver(site_url=settings.BASE_URL) as driver:
  +            category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)
  +            category_page.load()
  +            category_page.add_to_cart()
  +
  +            order_page = selenium.OrderPage(driver)
  +            order_page.load()
  +            order_page.fill_contacts()
  +            order_page.make_order()
  +
  +            success_page = selenium.SuccessPage(driver)
  +            assert success_page.is_success()
       except (WebDriverException, AssertionError) as err:
           if self.request.retries + 1 > self.max_retries:
               # report on the last attempt
  
verification_info: {"golden_diff": "diff --git a/shopelectro/celery.py b/shopelectro/celery.py\n--- a/shopelectro/celery.py\n+++ b/shopelectro/celery.py\n@@ -37,7 +37,11 @@\n beat_schedule = {\n     'update-catalog': {\n         'task': 'shopelectro.tasks.update_catalog',\n-        'schedule': timedelta(hours=2),\n+        'schedule': timedelta(hours=2).total_seconds(),\n+    },\n+    'check-purchase': {\n+        'task': 'shopelectro.tasks.check_purchase',\n+        'schedule': timedelta(days=1).total_seconds(),\n     },\n }\n \n@@ -48,6 +52,11 @@\n         'routing_key': 'utils.command',\n         'priority': 30,\n     },\n+    'shopelectro.tasks.check_purchase': {\n+        'queue': 'command',\n+        'routing_key': 'utils.command',\n+        'priority': 20,\n+    },\n     'ecommerce.tasks.send_mail': {\n         'queue': 'mail',\n         'routing_key': 'utils.mail',\ndiff --git a/shopelectro/selenium/driver.py b/shopelectro/selenium/driver.py\n--- a/shopelectro/selenium/driver.py\n+++ b/shopelectro/selenium/driver.py\n@@ -17,5 +17,11 @@\n         self.site_url = site_url\n         self.wait = WebDriverWait(self, settings.SELENIUM_WAIT_SECONDS)\n \n+    def __enter__(self):\n+        return self\n+\n+    def __exit__(self, *args, **kwargs):\n+        self.quit()\n+\n     def get(self, url):\n         super().get(urljoin(self.site_url, url))\ndiff --git a/shopelectro/tasks.py b/shopelectro/tasks.py\n--- a/shopelectro/tasks.py\n+++ b/shopelectro/tasks.py\n@@ -63,8 +63,6 @@\n         collect_static()\n     ]\n \n-# @todo #690:30m Schedule check_purchase in the celery beat.\n-\n \n @app.task(\n     bind=True,\n@@ -73,18 +71,18 @@\n )\n def check_purchase(self):\n     try:\n-        driver = selenium.SiteDriver(site_url=settings.BASE_URL)\n-        category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)\n-        category_page.load()\n-        category_page.add_to_cart()\n-\n-        order_page = selenium.OrderPage(driver)\n-        order_page.load()\n-        order_page.fill_contacts()\n-        order_page.make_order()\n-\n-        success_page = selenium.SuccessPage(driver)\n-        assert success_page.is_success()\n+        with selenium.SiteDriver(site_url=settings.BASE_URL) as driver:\n+            category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)\n+            category_page.load()\n+            category_page.add_to_cart()\n+\n+            order_page = selenium.OrderPage(driver)\n+            order_page.load()\n+            order_page.fill_contacts()\n+            order_page.make_order()\n+\n+            success_page = selenium.SuccessPage(driver)\n+            assert success_page.is_success()\n     except (WebDriverException, AssertionError) as err:\n         if self.request.retries + 1 > self.max_retries:\n             # report on the last attempt\n", "issue": "Make SiteDriver a context manager\nIt will provide convenient api to manage selenium resources and properly shout down selenium driver.   \n", "before_files": [{"content": "from contextlib import contextmanager\n\nfrom django.conf import settings\nfrom django.core.management import call_command\nfrom selenium.common.exceptions import WebDriverException\n\nfrom shopelectro import selenium\nfrom shopelectro.celery import app\nfrom shopelectro.report import TelegramReport\nfrom shopelectro.models import CategoryPage\nfrom shopelectro.management.commands._update_catalog import utils\n\n\n@contextmanager\ndef report():\n    try:\n        yield\n    except Exception as error:\n        utils.report(str(error))\n        raise error\n\n\n@app.task\ndef generate_price_files():\n    with report():\n        call_command('price')\n        print('Generate prices complete.')\n\n\n@app.task\ndef generate_excel_file():\n    with report():\n        call_command('excel')\n        print('Generate excel complete.')\n\n\n@app.task\ndef collect_static():\n    with report():\n        call_command('collectstatic', '--noinput')\n\n\n@app.task\ndef update_catalog_command():\n    with report():\n        call_command('update_catalog')\n\n\n@app.task\ndef update_default_templates():\n    with report():\n        call_command('update_default_templates')\n\n\n@app.task(autoretry_for=(Exception,), max_retries=3, default_retry_delay=60*10)  # Ignore PycodestyleBear (E226)\ndef update_catalog():\n    # http://docs.celeryproject.org/en/latest/userguide/canvas.html#map-starmap\n    return [\n        update_catalog_command(),\n        update_default_templates(),\n        generate_price_files(),\n        generate_excel_file(),\n        collect_static()\n    ]\n\n# @todo #690:30m Schedule check_purchase in the celery beat.\n\n\n@app.task(\n    bind=True,\n    autoretry_for=(WebDriverException, AssertionError),\n    retry_kwargs={'max_retries': settings.CHECK_PURCHASE_RETRIES},\n)\ndef check_purchase(self):\n    try:\n        driver = selenium.SiteDriver(site_url=settings.BASE_URL)\n        category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)\n        category_page.load()\n        category_page.add_to_cart()\n\n        order_page = selenium.OrderPage(driver)\n        order_page.load()\n        order_page.fill_contacts()\n        order_page.make_order()\n\n        success_page = selenium.SuccessPage(driver)\n        assert success_page.is_success()\n    except (WebDriverException, AssertionError) as err:\n        if self.request.retries + 1 > self.max_retries:\n            # report on the last attempt\n            TelegramReport().send(f'Can\\'t buy a product. Got the error: {err}')\n        raise err\n", "path": "shopelectro/tasks.py"}, {"content": "from urllib.parse import urljoin\n\nfrom django.conf import settings\nfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilities\nfrom selenium.webdriver.support.ui import WebDriverWait\nfrom seleniumrequests import Remote\n\n\nclass SiteDriver(Remote):\n    \"\"\"Provide convenient access to the site.\"\"\"\n\n    def __init__(self, *, site_url, **kwargs):\n        kwargs.setdefault('command_executor', settings.SELENIUM_URL)\n        kwargs.setdefault('desired_capabilities', DesiredCapabilities.CHROME)\n        super().__init__(**kwargs)\n\n        self.site_url = site_url\n        self.wait = WebDriverWait(self, settings.SELENIUM_WAIT_SECONDS)\n\n    def get(self, url):\n        super().get(urljoin(self.site_url, url))\n", "path": "shopelectro/selenium/driver.py"}, {"content": "from __future__ import absolute_import, unicode_literals\nfrom datetime import timedelta\nimport os\n\nfrom celery import Celery\nfrom kombu import Exchange, Queue\n\n# set the default Django settings module for the 'celery' program.\nos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shopelectro.settings.local')\n\napp = Celery('shopelectro')\n\n# Exchanges\ndefault_exchange = Exchange('default', type='direct')\nutils_exchange = Exchange('utils', type='direct')\n\n# http://docs.celeryproject.org/en/latest/userguide/tasks.html\ntask_queues = (\n    Queue(\n        name='default',\n        exchange=default_exchange,\n        routing_key='default',\n    ),\n    Queue(\n        name='mail',\n        exchange=utils_exchange,\n        routing_key='utils.mail',\n    ),\n    Queue(\n        name='command',\n        exchange=utils_exchange,\n        routing_key='utils.command',\n    )\n)\n\n# http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html\nbeat_schedule = {\n    'update-catalog': {\n        'task': 'shopelectro.tasks.update_catalog',\n        'schedule': timedelta(hours=2),\n    },\n}\n\n# http://docs.celeryproject.org/en/master/userguide/routing.html\ntask_routes = {\n    'shopelectro.tasks.update_catalog': {\n        'queue': 'command',\n        'routing_key': 'utils.command',\n        'priority': 30,\n    },\n    'ecommerce.tasks.send_mail': {\n        'queue': 'mail',\n        'routing_key': 'utils.mail',\n        'priority': 50,\n    },\n}\n\n# Using a string here means the worker don't have to serialize\n# the configuration object to child processes.\n# - namespace='CELERY' means all celery-related configuration keys\n#   should have a `CELERY_` prefix.\napp.config_from_object('django.conf:settings', namespace='CELERY')\n\n# http://docs.celeryproject.org/en/latest/userguide/configuration.html\n\nBROCKER_URL = (\n    f'amqp://{os.environ[\"RABBITMQ_DEFAULT_USER\"]}:{os.environ[\"RABBITMQ_DEFAULT_PASS\"]}'\n    f'@{os.environ[\"RABBITMQ_URL\"]}:{os.environ[\"RABBITMQ_PORT\"]}/'\n)\napp.conf.update(\n    broker_url=BROCKER_URL,\n    broker_heartbeat=30,\n    task_acks_late=True,\n    task_default_queue='default',\n    task_default_exchange='default',\n    task_default_routing_key='default',\n    task_ignore_result=True,\n    worker_pool_restarts=1000,\n    task_routes=task_routes,\n    task_queues=task_queues,\n    beat_schedule=beat_schedule,\n)\n\n# Load task modules from all registered Django app configs.\napp.autodiscover_tasks()\n", "path": "shopelectro/celery.py"}], "after_files": [{"content": "from contextlib import contextmanager\n\nfrom django.conf import settings\nfrom django.core.management import call_command\nfrom selenium.common.exceptions import WebDriverException\n\nfrom shopelectro import selenium\nfrom shopelectro.celery import app\nfrom shopelectro.report import TelegramReport\nfrom shopelectro.models import CategoryPage\nfrom shopelectro.management.commands._update_catalog import utils\n\n\n@contextmanager\ndef report():\n    try:\n        yield\n    except Exception as error:\n        utils.report(str(error))\n        raise error\n\n\n@app.task\ndef generate_price_files():\n    with report():\n        call_command('price')\n        print('Generate prices complete.')\n\n\n@app.task\ndef generate_excel_file():\n    with report():\n        call_command('excel')\n        print('Generate excel complete.')\n\n\n@app.task\ndef collect_static():\n    with report():\n        call_command('collectstatic', '--noinput')\n\n\n@app.task\ndef update_catalog_command():\n    with report():\n        call_command('update_catalog')\n\n\n@app.task\ndef update_default_templates():\n    with report():\n        call_command('update_default_templates')\n\n\n@app.task(autoretry_for=(Exception,), max_retries=3, default_retry_delay=60*10)  # Ignore PycodestyleBear (E226)\ndef update_catalog():\n    # http://docs.celeryproject.org/en/latest/userguide/canvas.html#map-starmap\n    return [\n        update_catalog_command(),\n        update_default_templates(),\n        generate_price_files(),\n        generate_excel_file(),\n        collect_static()\n    ]\n\n\n@app.task(\n    bind=True,\n    autoretry_for=(WebDriverException, AssertionError),\n    retry_kwargs={'max_retries': settings.CHECK_PURCHASE_RETRIES},\n)\ndef check_purchase(self):\n    try:\n        with selenium.SiteDriver(site_url=settings.BASE_URL) as driver:\n            category_page = selenium.CategoryPage(driver, CategoryPage.objects.first().slug)\n            category_page.load()\n            category_page.add_to_cart()\n\n            order_page = selenium.OrderPage(driver)\n            order_page.load()\n            order_page.fill_contacts()\n            order_page.make_order()\n\n            success_page = selenium.SuccessPage(driver)\n            assert success_page.is_success()\n    except (WebDriverException, AssertionError) as err:\n        if self.request.retries + 1 > self.max_retries:\n            # report on the last attempt\n            TelegramReport().send(f'Can\\'t buy a product. Got the error: {err}')\n        raise err\n", "path": "shopelectro/tasks.py"}, {"content": "from urllib.parse import urljoin\n\nfrom django.conf import settings\nfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilities\nfrom selenium.webdriver.support.ui import WebDriverWait\nfrom seleniumrequests import Remote\n\n\nclass SiteDriver(Remote):\n    \"\"\"Provide convenient access to the site.\"\"\"\n\n    def __init__(self, *, site_url, **kwargs):\n        kwargs.setdefault('command_executor', settings.SELENIUM_URL)\n        kwargs.setdefault('desired_capabilities', DesiredCapabilities.CHROME)\n        super().__init__(**kwargs)\n\n        self.site_url = site_url\n        self.wait = WebDriverWait(self, settings.SELENIUM_WAIT_SECONDS)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args, **kwargs):\n        self.quit()\n\n    def get(self, url):\n        super().get(urljoin(self.site_url, url))\n", "path": "shopelectro/selenium/driver.py"}, {"content": "from __future__ import absolute_import, unicode_literals\nfrom datetime import timedelta\nimport os\n\nfrom celery import Celery\nfrom kombu import Exchange, Queue\n\n# set the default Django settings module for the 'celery' program.\nos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shopelectro.settings.local')\n\napp = Celery('shopelectro')\n\n# Exchanges\ndefault_exchange = Exchange('default', type='direct')\nutils_exchange = Exchange('utils', type='direct')\n\n# http://docs.celeryproject.org/en/latest/userguide/tasks.html\ntask_queues = (\n    Queue(\n        name='default',\n        exchange=default_exchange,\n        routing_key='default',\n    ),\n    Queue(\n        name='mail',\n        exchange=utils_exchange,\n        routing_key='utils.mail',\n    ),\n    Queue(\n        name='command',\n        exchange=utils_exchange,\n        routing_key='utils.command',\n    )\n)\n\n# http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html\nbeat_schedule = {\n    'update-catalog': {\n        'task': 'shopelectro.tasks.update_catalog',\n        'schedule': timedelta(hours=2).total_seconds(),\n    },\n    'check-purchase': {\n        'task': 'shopelectro.tasks.check_purchase',\n        'schedule': timedelta(days=1).total_seconds(),\n    },\n}\n\n# http://docs.celeryproject.org/en/master/userguide/routing.html\ntask_routes = {\n    'shopelectro.tasks.update_catalog': {\n        'queue': 'command',\n        'routing_key': 'utils.command',\n        'priority': 30,\n    },\n    'shopelectro.tasks.check_purchase': {\n        'queue': 'command',\n        'routing_key': 'utils.command',\n        'priority': 20,\n    },\n    'ecommerce.tasks.send_mail': {\n        'queue': 'mail',\n        'routing_key': 'utils.mail',\n        'priority': 50,\n    },\n}\n\n# Using a string here means the worker don't have to serialize\n# the configuration object to child processes.\n# - namespace='CELERY' means all celery-related configuration keys\n#   should have a `CELERY_` prefix.\napp.config_from_object('django.conf:settings', namespace='CELERY')\n\n# http://docs.celeryproject.org/en/latest/userguide/configuration.html\n\nBROCKER_URL = (\n    f'amqp://{os.environ[\"RABBITMQ_DEFAULT_USER\"]}:{os.environ[\"RABBITMQ_DEFAULT_PASS\"]}'\n    f'@{os.environ[\"RABBITMQ_URL\"]}:{os.environ[\"RABBITMQ_PORT\"]}/'\n)\napp.conf.update(\n    broker_url=BROCKER_URL,\n    broker_heartbeat=30,\n    task_acks_late=True,\n    task_default_queue='default',\n    task_default_exchange='default',\n    task_default_routing_key='default',\n    task_ignore_result=True,\n    worker_pool_restarts=1000,\n    task_routes=task_routes,\n    task_queues=task_queues,\n    beat_schedule=beat_schedule,\n)\n\n# Load task modules from all registered Django app configs.\napp.autodiscover_tasks()\n", "path": "shopelectro/celery.py"}]}