Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Celery Beat Health Check: Check for Overdue Tasks Accounting for Scheduler Interval #297

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

Maker-Mark
Copy link

Overview of Health Check beat_health_check

The CeleryBeatHealth Check:
Checks for overdue tasks in a celery beat scheduler.
Uses the scheduler module dotted path that is specified in settings.py with CELERY_BEAT_SCHEDULER.
If not specified, defaults to django_celery_beat's django_celery_beat.schedulers.DatabaseScheduler.
Allows a custom buffer to be set using BEAT_HEALTH_CHECK_BUFFER_SECONDS in settings.py. The buffer
defaults to 30 seconds if not defined. The buffer will offset the scheduler interval for when due
tasks are processed. Using a buffer avoids false positives, such as the case where a task is
technically due according to the scheduler, but that's only because the scheduler has not hit its
interval to check and process due tasks.

I would love a review on this check and will be happy to address comments in a timely fashion.
Thanks!

@Maker-Mark Maker-Mark changed the title Celery Beat Health Check: Check for overdue tasks using configurable buffer Celery Beat Health Check: Check for Overdue Tasks Accounting for Scheduler Interval Apr 27, 2021
@Maker-Mark
Copy link
Author

@codingjoe Is there a contributing doc that I should be looking at? I can't seem to find how to request a review from a maintainer. Thanks.

@Maker-Mark
Copy link
Author

@skarzi Can I please get a review on this? I've had this open for a long time.

README.rst Outdated Show resolved Hide resolved
@@ -16,9 +16,11 @@ The following health checks are bundled with this project:
- AWS S3 storage
- Celery task queue
- Celery ping
- Celery Beat Health Check (via `django_celery_beat`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why using django_celery_beat is required? Have you checked if this check could be implemented based only on celery?

technically due according to the scheduler, but that's only because the scheduler has not hit its
interval to check and process due tasks.
"""
from celery.app import default_app as celery_app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the current_app proxy to get the currently used app, not the default one (fallback one)
Also, I think (but haven't tested it) that this import can be moved to the root module imports section because current_app is just a proxy.

scheduler = import_string(scheduler_module_path)
try:
# Get the celery scheduler for the current app and scheduler class via a beat Service
schedule: Dict = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIP: always add type hintings for key and value when using Dict

Comment on lines +37 to +38
schedule_tasks: Union[ModelEntry, Any] = schedule.values()
tasks_due: List[Union[ModelEntry, Any]] = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to get rid of Any in type hintings because it makes them too vague

bool: If the task is overdue by at least the buffer.
"""
EXPECTED_SCHEDULE_CLASSES = [solar, crontab, schedule]
DEFAULT_DUE_BUFFER_SECONDS = 30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIP: let's move it to module-level constant. Also Final type annotation can be used to indicate it's a constant

try:
celery_schedule: Union[solar, crontab, schedule] = task_schedule.schedule
due_in = celery_schedule.remaining_estimate(task.last_run_at)
except BaseException:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use Exception or narrow possible exception type even more

health_check/contrib/beat_health_check/backends.py Outdated Show resolved Hide resolved
health_check/contrib/beat_health_check/backends.py Outdated Show resolved Hide resolved

# Get the celery schedule from the Modelentry.
celery_scheduler = task_schedule.schedule
if celery_scheduler.__class__ not in EXPECTED_SCHEDULE_CLASSES:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not isinstance(celery_scheduler, ...)?

@sevdog
Copy link

sevdog commented May 14, 2024

Is this PR going to be updated or merged sooner o later?

It will be very good to also have a checker for celery-beat.

@Maker-Mark
Copy link
Author

@sevdog Hey, sorry I got busy and did not update the author's feedback. Do you want to finish it up? Or I can try to get to it in a few weeks, but no promises.

@sevdog
Copy link

sevdog commented May 15, 2024

Hi @Maker-Mark, currently I also have few spare time to work on this. I was just trying to ping for more help regarding celery support in this package. Feel free to work on this when you get some time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants