From 46d61a9c764e3f7e0514bac6c2fe5718cecaf128 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Tue, 27 Jan 2026 17:23:27 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(backend)=20correctly=20configure?= =?UTF-8?q?=20celery=20beat=20to=20run=20wopi=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The celery beat configuration was not working correctly, we installed the database scheduler but we didn't configure it correctly. We prefer removing this scheduler to use the default one. Instead, the crontab part can be configured using environment variable. By default it will be run every night at 3AM. --- .dockerignore | 1 + .gitignore | 1 + CHANGELOG.md | 5 +++ docs/env.md | 12 +++++++ src/backend/drive/settings.py | 17 ++++++++-- src/backend/pyproject.toml | 1 - src/backend/uv.lock | 40 ------------------------ src/backend/wopi/tasks/configure_wopi.py | 11 +++++-- 8 files changed, 42 insertions(+), 46 deletions(-) diff --git a/.dockerignore b/.dockerignore index 23ff73ca..f5bb4b9c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -31,6 +31,7 @@ db.sqlite3 .mypy_cache .pylint.d .pytest_cache +**/celerybeat-schedule* # Frontend node_modules diff --git a/.gitignore b/.gitignore index 083bf553..2f9a22de 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ share/python-wheels/ MANIFEST .DS_Store .next/ +celerybeat-schedule* # Translations # Translations *.mo diff --git a/CHANGELOG.md b/CHANGELOG.md index 6afa9005..e530059c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,10 +16,15 @@ and this project adheres to - 🔥(backend) remove usage of atomic transaction for item creation +### Fixed + +- 🐛(backend) correctly configure celery beat to run wopi configuration + ### Security - 🔒️(backend) prevent mismatch mimetype between object storage and application + ## [v0.11.1] - 2026-01-13 ### Fixed diff --git a/docs/env.md b/docs/env.md index 29fc9884..f882590a 100644 --- a/docs/env.md +++ b/docs/env.md @@ -108,3 +108,15 @@ This document lists all configurable environment variables for the Drive applica | `SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK` | Enable Django deploy check in Spectacular | `False` | | `STORAGES_STATICFILES_BACKEND` | Backend for static files storage | `whitenoise.storage.CompressedManifestStaticFilesStorage` | | `TRASHBIN_CUTOFF_DAYS` | Number of days before items are permanently deleted from trash | `30` | +| `WOPI_CLIENTS` | List of client name. These client names will be used in the post_setup | [] | +| `WOPI_{CLIENT_NAME}_DISCOVERY_URL` | The discovery url for each client present in the `WOPI_CLIENTS`. if `WOPI_CLIENTS=vendorA` then set `WOPI_VENDORA_DISCOVERY_URL` | | +| `WOPI_EXCLUDED_MIMETYPES` | List of mimetypes excluded when parsing the discovery url | See settings.py module | +| `WOPI_EXCLUDED_EXTENSIONS` | List of extensions excluded when parsing the discovery url | See settings.py module | +| `WOPI_SRC_BASE_URL` | The backend url | None | +| `WOPI_ACCESS_TOKEN_TIMEOUT` | TTL in seconds for the access_token_ttl sent to the WOPI client | `36000` (10H) | +| `WOPI_LOCK_TIMEOUT` | TTL for the lock acquired by a WOPI client | `1800` (30 min) | +| `WOPI_DISABLE_CHAT` | Disable chat in the WOPI client interface | `0` | +| `WOPI_CONFIGURATION_CRONTAB_MINUTE` | Used to configure the celery beat crontab, See https://docs.celeryq.dev/en/main/reference/celery.schedules.html#celery.schedules.crontab | `0` | +| `WOPI_CONFIGURATION_CRONTAB_HOUR` | Used to configure the celery beat crontab, See https://docs.celeryq.dev/en/main/reference/celery.schedules.html#celery.schedules.crontab | `3` | +| `WOPI_CONFIGURATION_CRONTAB_DAY_OF_MONTH` | Used to configure the celery beat crontab, See https://docs.celeryq.dev/en/main/reference/celery.schedules.html#celery.schedules.crontab | `*` | +| `WOPI_CONFIGURATION_CRONTAB_MONTH_OF_YEAR` | Used to configure the celery beat crontab, See https://docs.celeryq.dev/en/main/reference/celery.schedules.html#celery.schedules.crontab | `*` | diff --git a/src/backend/drive/settings.py b/src/backend/drive/settings.py index 1fb2efb1..093d8a34 100755 --- a/src/backend/drive/settings.py +++ b/src/backend/drive/settings.py @@ -833,7 +833,6 @@ class Base(Configuration): "drf_standardized_errors", # Third party apps "corsheaders", - "django_celery_beat", "django_filters", "dockerflow.django", "rest_framework", @@ -1049,7 +1048,6 @@ class Base(Configuration): # Celery CELERY_BROKER_URL = values.Value("redis://redis:6379/0") CELERY_BROKER_TRANSPORT_OPTIONS = values.DictValue({}) - CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" # Session SESSION_ENGINE = "django.contrib.sessions.backends.cache" @@ -1391,6 +1389,21 @@ class Base(Configuration): 0, environ_name="WOPI_DISABLE_CHAT", environ_prefix=None ) + WOPI_CONFIGURATION_CRONTAB_MINUTE = values.Value( + 0, environ_name="WOPI_CONFIGURATION_CRONTAB_MINUTE", environ_prefix=None + ) + WOPI_CONFIGURATION_CRONTAB_HOUR = values.Value( + 3, environ_name="WOPI_CONFIGURATION_CRONTAB_HOUR", environ_prefix=None + ) + WOPI_CONFIGURATION_CRONTAB_DAY_OF_MONTH = values.Value( + "*", environ_name="WOPI_CONFIGURATION_CRONTAB_DAY_OF_MONTH", environ_prefix=None + ) + WOPI_CONFIGURATION_CRONTAB_MONTH_OF_YEAR = values.Value( + "*", + environ_name="WOPI_CONFIGURATION_CRONTAB_MONTH_OF_YEAR", + environ_prefix=None, + ) + # Malware detection MALWARE_DETECTION = { "BACKEND": values.Value( diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index 43ffc379..e9b54873 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -30,7 +30,6 @@ dependencies = [ "celery[redis]==5.6.2", "defusedxml==0.7.1", "django<6.0.0", - "django-celery-beat==2.8.1", "django-configurations==2.5.1", "django-cors-headers==4.9.0", "django-countries==8.2.0", diff --git a/src/backend/uv.lock b/src/backend/uv.lock index ce8b166b..87c0cc02 100644 --- a/src/backend/uv.lock +++ b/src/backend/uv.lock @@ -289,18 +289,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/a3/43b749004e3c09452e39bb56347a008f0a0668aad37324a99b5c8ca91d9e/coverage-7.12.0-py3-none-any.whl", hash = "sha256:159d50c0b12e060b15ed3d39f87ed43d4f7f7ad40b8a534f4dd331adbb51104a", size = 209503, upload-time = "2025-11-18T13:34:18.892Z" }, ] -[[package]] -name = "cron-descriptor" -version = "2.0.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7c/31/0b21d1599656b2ffa6043e51ca01041cd1c0f6dacf5a3e2b620ed120e7d8/cron_descriptor-2.0.6.tar.gz", hash = "sha256:e39d2848e1d8913cfb6e3452e701b5eec662ee18bea8cc5aa53ee1a7bb217157", size = 49456, upload-time = "2025-09-03T16:30:22.434Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/21/cc/361326a54ad92e2e12845ad15e335a4e14b8953665007fb514d3393dfb0f/cron_descriptor-2.0.6-py3-none-any.whl", hash = "sha256:3a1c0d837c0e5a32e415f821b36cf758eb92d510e6beff8fbfe4fa16573d93d6", size = 74446, upload-time = "2025-09-03T16:30:21.397Z" }, -] - [[package]] name = "cryptography" version = "46.0.3" @@ -404,23 +392,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/17/b0/7f42bfc38b8f19b78546d47147e083ed06e12fc29c42da95655e0962c6c2/django-5.2.9-py3-none-any.whl", hash = "sha256:3a4ea88a70370557ab1930b332fd2887a9f48654261cdffda663fef5976bb00a", size = 8290652, upload-time = "2025-12-02T14:01:03.485Z" }, ] -[[package]] -name = "django-celery-beat" -version = "2.8.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "celery" }, - { name = "cron-descriptor" }, - { name = "django" }, - { name = "django-timezone-field" }, - { name = "python-crontab" }, - { name = "tzdata" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/aa/11/0c8b412869b4fda72828572068312b10aafe7ccef7b41af3633af31f9d4b/django_celery_beat-2.8.1.tar.gz", hash = "sha256:dfad0201c0ac50c91a34700ef8fa0a10ee098cc7f3375fe5debed79f2204f80a", size = 175802, upload-time = "2025-05-13T06:58:29.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/61/e5/3a0167044773dee989b498e9a851fc1663bea9ab879f1179f7b8a827ac10/django_celery_beat-2.8.1-py3-none-any.whl", hash = "sha256:da2b1c6939495c05a551717509d6e3b79444e114a027f7b77bf3727c2a39d171", size = 104833, upload-time = "2025-05-13T06:58:27.309Z" }, -] - [[package]] name = "django-configurations" version = "2.5.1" @@ -669,7 +640,6 @@ dependencies = [ { name = "defusedxml" }, { name = "dj-database-url" }, { name = "django" }, - { name = "django-celery-beat" }, { name = "django-configurations" }, { name = "django-cors-headers" }, { name = "django-countries" }, @@ -732,7 +702,6 @@ requires-dist = [ { name = "defusedxml", specifier = "==0.7.1" }, { name = "dj-database-url", specifier = "==3.0.1" }, { name = "django", specifier = "<6.0.0" }, - { name = "django-celery-beat", specifier = "==2.8.1" }, { name = "django-configurations", specifier = "==2.5.1" }, { name = "django-cors-headers", specifier = "==4.9.0" }, { name = "django-countries", specifier = "==8.2.0" }, @@ -1416,15 +1385,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] -[[package]] -name = "python-crontab" -version = "3.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/99/7f/c54fb7e70b59844526aa4ae321e927a167678660ab51dda979955eafb89a/python_crontab-3.3.0.tar.gz", hash = "sha256:007c8aee68dddf3e04ec4dce0fac124b93bd68be7470fc95d2a9617a15de291b", size = 57626, upload-time = "2025-07-13T20:05:35.535Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/47/42/bb4afa5b088f64092036221843fc989b7db9d9d302494c1f8b024ee78a46/python_crontab-3.3.0-py3-none-any.whl", hash = "sha256:739a778b1a771379b75654e53fd4df58e5c63a9279a63b5dfe44c0fcc3ee7884", size = 27533, upload-time = "2025-07-13T20:05:34.266Z" }, -] - [[package]] name = "python-dateutil" version = "2.9.0.post0" diff --git a/src/backend/wopi/tasks/configure_wopi.py b/src/backend/wopi/tasks/configure_wopi.py index 082eb83a..cf3965c0 100644 --- a/src/backend/wopi/tasks/configure_wopi.py +++ b/src/backend/wopi/tasks/configure_wopi.py @@ -17,13 +17,18 @@ WOPI_DEFAULT_CONFIGURATION = { } -@celery_app.on_after_configure.connect +@celery_app.on_after_finalize.connect def setup_periodic_tasks(sender: Celery, **kwargs): """Setup periodic tasks.""" sender.add_periodic_task( - crontab(minute="0"), + crontab( + minute=settings.WOPI_CONFIGURATION_CRONTAB_MINUTE, + hour=settings.WOPI_CONFIGURATION_CRONTAB_HOUR, + day_of_month=settings.WOPI_CONFIGURATION_CRONTAB_DAY_OF_MONTH, + month_of_year=settings.WOPI_CONFIGURATION_CRONTAB_MONTH_OF_YEAR, + ), configure_wopi_clients.s(), - name="configure_wopi_clients_every_hour", + name="configure_wopi_clients", serializer="json", )