Skip to content

Dry-run Database Scheduler#968

Open
andreangelucci wants to merge 6 commits intocelery:mainfrom
andreangelucci:dry-run-scheduler
Open

Dry-run Database Scheduler#968
andreangelucci wants to merge 6 commits intocelery:mainfrom
andreangelucci:dry-run-scheduler

Conversation

@andreangelucci
Copy link
Copy Markdown

@andreangelucci andreangelucci commented Oct 29, 2025

Description

Introduces the DryRunDatabaseScheduler to read Periodic Tasks from the database while operating in dry-run mode.

The dry-run mode is useful for setting up projects with Periodic Tasks stored in the Django database while skipping their execution in development environments lower than production, such as local environments.

The Scheduler class inherits from DatabaseScheduler and overwrites the apply_entry method to log the triggered tasks instead of actually running them.


Fixes: #942

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a DryRunDatabaseScheduler class that reads periodic tasks from the database while operating in dry-run mode, preventing task execution in development environments. This addresses issue #942 by allowing developers to test scheduler configuration without triggering actual task execution.

Changes:

  • Added new DryRunDatabaseScheduler class that inherits from DatabaseScheduler
  • Overrides apply_entry method to log scheduled tasks instead of executing them

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread django_celery_beat/schedulers.py Outdated
Comment thread django_celery_beat/schedulers.py
Comment on lines +528 to +547
class DryRunDatabaseScheduler(DatabaseScheduler):
"""
DatabaseScheduler in dry-run mode.

The Scheduler reads Periodic Tasks from the database but does not execute them,
only logging when they would have been triggered.
Useful in environments where tasks should not actually run, but the scheduler
must remain operational.
"""

def apply_entry(self, entry, producer=None):
"""
Overwritten method to log the triggered tasks instead of actually running it.
"""
debug(
'Dry-run mode: Skipping task %s %s %s',
entry.task,
entry.args,
entry.kwargs
)
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The new DryRunDatabaseScheduler class lacks test coverage. Given that the repository has comprehensive test coverage for the DatabaseScheduler (in t/unit/test_schedulers.py), tests should be added to verify the dry-run behavior, including confirming that tasks are logged but not executed, and that the scheduler functions correctly without affecting task execution.

Copilot uses AI. Check for mistakes.
Comment on lines +528 to +547
class DryRunDatabaseScheduler(DatabaseScheduler):
"""
DatabaseScheduler in dry-run mode.

The Scheduler reads Periodic Tasks from the database but does not execute them,
only logging when they would have been triggered.
Useful in environments where tasks should not actually run, but the scheduler
must remain operational.
"""

def apply_entry(self, entry, producer=None):
"""
Overwritten method to log the triggered tasks instead of actually running it.
"""
debug(
'Dry-run mode: Skipping task %s %s %s',
entry.task,
entry.args,
entry.kwargs
)
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

Documentation is missing for the new DryRunDatabaseScheduler. Consider adding usage examples to the documentation (such as in docs/includes/introduction.txt) showing how to configure and use the dry-run scheduler, similar to how the DatabaseScheduler is documented. Users should know how to enable this scheduler in their development environments.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

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

Interesting stuff! but we will need tests and some times to decided before merging this

@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.70%. Comparing base (a0700a0) to head (422f88c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #968      +/-   ##
==========================================
+ Coverage   87.64%   87.70%   +0.06%     
==========================================
  Files          32       32              
  Lines        1012     1017       +5     
  Branches       81       81              
==========================================
+ Hits          887      892       +5     
  Misses        107      107              
  Partials       18       18              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cclauss
Copy link
Copy Markdown
Contributor

cclauss commented Mar 2, 2026

This will need to be rebased to the current main branch.

entry.kwargs
)

def sync(self):
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@auvipy , thanks for this suggestion.

I understand that we are skipping the metadata update in dry-run mode since the task wasn't actually executed. But don't we need to store the attempt of execution to prevent breaking the scheduler loop? For an hourly task, for example, don't we want to persist the execution attempt?

If not, it will only be stored in memory, right? Any refresh of the tasks in the event loop will confuse the scheduler.

@andreangelucci andreangelucci requested a review from auvipy April 4, 2026 13:41
André Angeluci and others added 6 commits April 5, 2026 11:10
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +568 to +580
def sync(self):
"""
Override sync to avoid persisting execution metadata in dry-run mode.

In DatabaseScheduler, sync() saves dirty entries (including updated
last_run_at and total_run_count) back to the database. For a dry-run
scheduler this would be misleading, since tasks are never actually run.

By overriding sync as a no-op, we ensure that dry-run operation does not
modify PeriodicTask records in the database while still allowing the
scheduler machinery to operate normally.
"""
debug('Dry-run mode: Skipping database sync of scheduled tasks.')
Comment thread t/unit/test_schedulers.py
Comment on lines +1471 to +1472


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.

How to disable Celery beat tasks globally?

4 participants