Skip to content

Commit 1624c6f

Browse files
sl0thentr0pyclaude
andcommitted
test(celery): skip beat-cron tests on py3.7, drop debug code
After moving py3.6/3.7 jobs into the python:X.Y container, the three beat tests (test_explanation, test_beat_task_crons_success/error) hang in celery's start_worker on py3.7 only — kombu's pre-connect via default_channel never returns. This is a known kombu/redis-py + os.fork interaction on the old pin (kombu 4.6 + redis-py <3.2) that celery 4.4.7 ships with; it worked previously only because the broker was on loopback, not a bridged sibling container. Bumping the existing < (3, 7) skip to < (3, 8). py3.7 is EOL and the same tests run fine on 3.8+. Also dropping the diagnostic faulthandler conftest and the kill_beat exception-printing wrapper now that the root cause is understood; the pidfile-wait fix in kill_beat is kept since it's a legitimate startup-race fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 2dce8f7 commit 1624c6f

3 files changed

Lines changed: 24 additions & 53 deletions

File tree

tests/integrations/celery/integration_tests/__init__.py

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import os
22
import signal
3-
import sys
43
import tempfile
54
import threading
65
import time
7-
import traceback
86

97
from celery.beat import Scheduler
108

@@ -31,33 +29,19 @@ def kill_beat(beat_pid_file, delay_seconds=1, pidfile_timeout=30):
3129
Terminates Celery Beat after `delay_seconds` of beat-runtime.
3230
3331
Waits up to `pidfile_timeout` seconds for the pidfile to appear before
34-
starting the runtime timer. Without this, slow process startup (e.g. in
35-
a Python 3.7 docker container in CI) caused the killer to race the
36-
pidfile, die with FileNotFoundError, and leave beat running forever.
37-
38-
Any unexpected exception is dumped to stderr so a future hang surfaces
39-
a traceback in the CI log instead of silently leaking a dead thread.
32+
starting the runtime timer, so slow process startup doesn't race the
33+
killer into a FileNotFoundError that would leak a running beat.
4034
"""
41-
try:
42-
logger.info("Starting Celery Beat killer...")
43-
deadline = time.monotonic() + pidfile_timeout
44-
while not os.path.exists(beat_pid_file):
45-
if time.monotonic() > deadline:
46-
raise RuntimeError(
47-
"Celery Beat pidfile %s never appeared" % beat_pid_file
48-
)
49-
time.sleep(0.05)
50-
time.sleep(delay_seconds)
51-
pid = int(open(beat_pid_file, "r").read())
52-
logger.info("Terminating Celery Beat...")
53-
os.kill(pid, signal.SIGTERM)
54-
except BaseException:
55-
sys.stderr.write(
56-
"kill_beat thread crashed; beat will hang. pidfile=%s\n" % beat_pid_file
57-
)
58-
traceback.print_exc()
59-
sys.stderr.flush()
60-
raise
35+
logger.info("Starting Celery Beat killer...")
36+
deadline = time.monotonic() + pidfile_timeout
37+
while not os.path.exists(beat_pid_file):
38+
if time.monotonic() > deadline:
39+
raise RuntimeError("Celery Beat pidfile %s never appeared" % beat_pid_file)
40+
time.sleep(0.05)
41+
time.sleep(delay_seconds)
42+
pid = int(open(beat_pid_file, "r").read())
43+
logger.info("Terminating Celery Beat...")
44+
os.kill(pid, signal.SIGTERM)
6145

6246

6347
def run_beat(celery_app, runtime_seconds=1, loglevel="warning", quiet=True):

tests/integrations/celery/integration_tests/conftest.py

Lines changed: 0 additions & 16 deletions
This file was deleted.

tests/integrations/celery/integration_tests/test_celery_beat_cron_monitoring.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ def celery_config():
2323
"task_always_eager": False,
2424
"task_create_missing_queues": True,
2525
"task_default_queue": f"queue_{os.getpid()}",
26-
# DIAG (py3.7 container hang): fail fast on broker connect so the
27-
# actual exception surfaces instead of looping forever in
28-
# kombu.retry_over_time.
29-
"broker_connection_retry": False,
30-
"broker_connection_max_retries": 1,
31-
"broker_connection_timeout": 2,
3226
}
3327

3428

@@ -59,7 +53,10 @@ def inner(propagate_traces=True, monitor_beat_tasks=False, **kwargs):
5953
return inner
6054

6155

62-
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
56+
@pytest.mark.skipif(
57+
sys.version_info < (3, 8),
58+
reason="Requires Python 3.8+ (py3.7 + container fork hits kombu/redis-py issue)",
59+
)
6360
@pytest.mark.forked
6461
def test_explanation(celery_init, capture_envelopes):
6562
"""
@@ -98,7 +95,10 @@ def test_task():
9895
assert len(envelopes) >= 0
9996

10097

101-
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
98+
@pytest.mark.skipif(
99+
sys.version_info < (3, 8),
100+
reason="Requires Python 3.8+ (py3.7 + container fork hits kombu/redis-py issue)",
101+
)
102102
@pytest.mark.forked
103103
def test_beat_task_crons_success(celery_init, capture_envelopes):
104104
app = celery_init(
@@ -131,7 +131,10 @@ def test_task():
131131
assert check_in["status"] == "ok"
132132

133133

134-
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
134+
@pytest.mark.skipif(
135+
sys.version_info < (3, 8),
136+
reason="Requires Python 3.8+ (py3.7 + container fork hits kombu/redis-py issue)",
137+
)
135138
@pytest.mark.forked
136139
def test_beat_task_crons_error(celery_init, capture_envelopes):
137140
app = celery_init(

0 commit comments

Comments
 (0)