• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kobotoolbox / kpi / 24132020822
82%
master: 76%

Build:
Build:
LAST BUILD BRANCH: main
DEFAULT BRANCH: master
Ran 08 Apr 2026 11:08AM UTC
Jobs 10
Files 889
Run time 2min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

08 Apr 2026 11:03AM UTC coverage: 81.698% (-0.02%) from 81.717%
24132020822

push

github

web-flow
perf(beat): throttle Beat schedule reloads to fix dispatch starvation DEV-1963 (#6926)

### 👷 Description for instance maintainers

On high-volume servers (Global), Celery Beat was spending most of its
time reloading its schedule instead of dispatching tasks. Root cause:
each completed trash-bin task deleted its `PeriodicTask` record
individually, triggering a `PeriodicTasks.changed()` DB signal that
forces Beat to reload all periodic tasks from scratch. With hundreds of
concurrent one-off tasks completing, this produced thousands of reload
signals per minute.

Two changes fix this:

1. **`ThrottledDatabaseScheduler`** (`kobo/apps/beat/schedulers.py`) — a
`DatabaseScheduler` subclass that gates full schedule reloads to at most
once every 15 seconds. Added as `CELERY_BEAT_SCHEDULER` in settings and
as `--scheduler` in the Beat entrypoint.

2. **Removed individual `PeriodicTask.delete()` calls** from
`process_deletion` (`trash_bin/utils/trash.py`) and the
`pre_delete_attachment` signal (`openrosa/apps/logger/signals.py`).
Orphaned `PeriodicTask` records are now cleaned up in batch by the
existing `garbage_collector` task (runs every 30 min) with signals
suppressed via `temporarily_disconnect_signals`.

### 💭 Notes

- `ThrottledDatabaseScheduler` always calls `super().schedule_changed()`
to keep `_last_timestamp` in sync with the DB — no change is ever
permanently missed, at most deferred by up to 15 s. For trash tasks
scheduled days in the future this is negligible.
- Orphaned `PeriodicTask` records are `one_off=True` and already
`enabled=False` (Beat marks them after dispatch). Beat loads only
`.objects.enabled()`, so orphans don't trigger any extra reload signals
while waiting for `garbage_collector`.
- Beat's own internal signal when it marks `one_off` tasks as
`enabled=False` after dispatch (1 per dispatched task) is still present
— it's internal to `django-celery-beat` and not addressable without
patching the library. The throttle absorbs this rema... (continued)

7441 of 11560 branches covered (64.37%)

3 of 25 new or added lines in 4 files covered. (12.0%)

1 existing line in 1 file now uncovered.

28568 of 34968 relevant lines covered (81.7%)

5.81 hits per line

Uncovered Changes

Lines Coverage ∆ File
21
0.0
kobo/apps/beat/schedulers.py
1
61.11
1.57% kobo/apps/openrosa/apps/logger/signals.py

Coverage Regressions

Lines Coverage ∆ File
1
57.36
0.44% kobo/apps/trash_bin/utils/trash.py
Jobs
ID Job ID Ran Files Coverage
1 24132020822.1 08 Apr 2026 11:08AM UTC 885
54.65
2 24132020822.2 08 Apr 2026 11:08AM UTC 885
53.17
3 24132020822.3 08 Apr 2026 11:08AM UTC 887
54.43
4 24132020822.4 08 Apr 2026 11:08AM UTC 887
55.94
5 24132020822.5 08 Apr 2026 11:09AM UTC 885
53.5
6 24132020822.6 08 Apr 2026 11:10AM UTC 885
60.41
7 24132020822.7 08 Apr 2026 11:10AM UTC 887
65.39
8 24132020822.8 08 Apr 2026 11:10AM UTC 887
61.57
9 24132020822.9 08 Apr 2026 11:11AM UTC 889
67.68
10 24132020822.10 08 Apr 2026 11:12AM UTC 887
54.89
Source Files on build 24132020822
  • Tree
  • List 889
  • Changed 7
  • Source Changed 0
  • Coverage Changed 7
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • 0ce5f9da on github
  • Prev Build on release/2.026.07 (#23954362374)
  • Next Build on release/2.026.07 (#24244591057)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc