diff --git a/Procfile b/Procfile index 065f381b..9bd6130d 100644 --- a/Procfile +++ b/Procfile @@ -1,3 +1,4 @@ release: ./manage.py migrate web: gunicorn --bind 0.0.0.0:$PORT miqa.wsgi -worker: REMAP_SIGTERM=SIGQUIT celery --app miqa.celery worker --loglevel INFO --without-heartbeat +# never use more than one worker; duplicate schedulers will result in duplicate tasks +worker: REMAP_SIGTERM=SIGQUIT celery --app miqa.celery worker --loglevel INFO --without-heartbeat -B diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 772120db..14453463 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -4,7 +4,7 @@ services: build: context: . dockerfile: ./dev/django.Dockerfile - command: ["./manage.py", "runserver", "0.0.0.0:8000"] + command: [ "./manage.py", "runserver", "0.0.0.0:8000" ] # Log printing via Rich is enhanced by a TTY tty: true env_file: ./dev/.env.docker-compose @@ -30,13 +30,17 @@ services: build: context: . dockerfile: ./dev/django.Dockerfile - command: [ - "celery", - "--app", "miqa.celery", - "worker", - "--loglevel", "INFO", - "--without-heartbeat" - ] + command: + [ + "celery", + "-A", + "miqa.celery", + "worker", + "--loglevel", + "INFO", + "--without-heartbeat", + "-B" # add celery beat worker to schedule automatic tasks + ] # Docker Compose does not set the TTY width, which causes Celery errors tty: false env_file: ./dev/.env.docker-compose @@ -50,7 +54,7 @@ services: npm: image: node:latest - command: ["npm", "run", "serve"] + command: [ "npm", "run", "serve" ] working_dir: /opt/client environment: # Fixes https://github.com/OpenImaging/miqa/issues/298 diff --git a/miqa/core/tasks.py b/miqa/core/tasks.py index 79fe8772..895fa12b 100644 --- a/miqa/core/tasks.py +++ b/miqa/core/tasks.py @@ -49,6 +49,16 @@ def _download_from_s3(path: str, public: bool) -> bytes: return buf.getvalue() +@shared_task +def reset_demo(): + demo_project = Project.objects.get(name='Demo Project') + demo_project.import_path = 's3://miqa-storage/miqa.csv' + demo_project.export_path = 'samples/demo.json' + demo_project.save() + import_data(demo_project.id) + Project.objects.exclude(id=demo_project.id).delete() + + @shared_task def evaluate_frame_content(frame_id): from miqa.learning.evaluation_models import available_evaluation_models diff --git a/miqa/settings.py b/miqa/settings.py index 7b3ce356..ee18b7fa 100644 --- a/miqa/settings.py +++ b/miqa/settings.py @@ -16,6 +16,7 @@ ) from composed_configuration._configuration import _BaseConfiguration from configurations import values +from celery.schedules import crontab class MiqaMixin(ConfigMixin): @@ -45,6 +46,9 @@ class MiqaMixin(ConfigMixin): # Override default signup sheet to ask new users for first and last name ACCOUNT_FORMS = {'signup': 'miqa.core.rest.accounts.AccountSignupForm'} + CELERY_BEAT_SCHEDULE = {} + + @staticmethod def before_binding(configuration: ComposedConfiguration) -> None: # Install local apps first, to ensure any overridden resources are found first @@ -85,6 +89,14 @@ def before_binding(configuration: ComposedConfiguration) -> None: 'EXCEPTION_HANDLER' ] = 'miqa.core.rest.exceptions.custom_exception_handler' + if configuration.DEMO_MODE: + configuration.CELERY_BEAT_SCHEDULE.update({ + 'reset-demo': { + 'task': 'miqa.core.tasks.reset_demo', + 'schedule': crontab(minute=0, hour=0), # daily at midnight + } + }) + class DevelopmentConfiguration(MiqaMixin, DevelopmentBaseConfiguration): HOMEPAGE_REDIRECT_URL = values.Value(environ=True, default='http://localhost:8081')