0001-don-t-start-a-new-cron-if-locked-18519.patch
tests/test_publisher.py | ||
---|---|---|
8 | 8 |
import zipfile |
9 | 9 | |
10 | 10 |
import mock |
11 |
import pytest |
|
11 | 12 | |
12 | 13 |
from django.core.management import call_command |
14 |
from django.core.management.base import CommandError |
|
13 | 15 |
from quixote import cleanup |
14 | 16 |
from wcs.qommon.http_request import HTTPRequest |
15 | 17 | |
... | ... | |
172 | 174 |
with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker: |
173 | 175 |
call_command('cron') |
174 | 176 |
assert cron_worker.call_count == 1 |
177 | ||
178 |
# simulate another locked cron |
|
179 |
import tempfile |
|
180 |
from qommon.vendor import locket |
|
181 |
lockfile = os.path.join(tempfile.gettempdir(), 'wcs-cron-in-progress.lock') |
|
182 |
with locket.lock_file(lockfile, timeout=0): |
|
183 |
with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker: |
|
184 |
call_command('cron') # silent by default (verbosity=0) |
|
185 |
assert cron_worker.call_count == 0 |
|
186 |
call_command('cron', verbosity=2) # same if verbosity>0 |
|
187 |
assert cron_worker.call_count == 0 |
|
188 |
# verify that the lock is released |
|
189 |
with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker: |
|
190 |
call_command('cron') |
|
191 |
assert cron_worker.call_count == 1 |
|
192 | ||
193 |
# simulate a cron crash |
|
194 |
with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker: |
|
195 |
cron_worker.side_effect = NotImplementedError |
|
196 |
with pytest.raises(NotImplementedError): |
|
197 |
call_command('cron') |
|
198 |
assert cron_worker.call_count == 1 |
|
199 |
# verify that the lock is released |
|
200 |
with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker: |
|
201 |
call_command('cron') |
|
202 |
assert cron_worker.call_count == 1 |
wcs/qommon/management/commands/cron.py | ||
---|---|---|
28 | 28 |
class Command(BaseCommand): |
29 | 29 |
help = 'Execute cronjobs' |
30 | 30 | |
31 |
def handle(self, verbosity, **options): |
|
32 |
with locket.lock_file(os.path.join(tempfile.gettempdir(), 'wcs-cron')): |
|
33 |
now = time.localtime() |
|
34 |
publisher_class = get_publisher_class() |
|
35 |
publisher_class.register_cronjobs() |
|
36 |
publisher = publisher_class.create_publisher() |
|
37 |
app_dir = publisher.app_dir |
|
38 |
for hostname in publisher.get_tenants(): |
|
39 |
publisher.app_dir = os.path.join(app_dir, hostname) |
|
40 |
cron_worker(publisher, now) |
|
31 |
def add_arguments(self, parser): |
|
32 |
parser.set_defaults(verbosity=0) |
|
33 | ||
34 |
def handle(self, verbosity, **kwargs): |
|
35 |
lockfile = os.path.join(tempfile.gettempdir(), 'wcs-cron-in-progress.lock') |
|
36 |
try: |
|
37 |
with locket.lock_file(lockfile, timeout=0): |
|
38 |
if verbosity > 2: |
|
39 |
print('cron start (lock %s)' % lockfile) |
|
40 |
now = time.localtime() |
|
41 |
publisher_class = get_publisher_class() |
|
42 |
publisher_class.register_cronjobs() |
|
43 |
publisher = publisher_class.create_publisher() |
|
44 |
app_dir = publisher.app_dir |
|
45 |
for hostname in publisher.get_tenants(): |
|
46 |
if verbosity > 1: |
|
47 |
print('cron work on %s' % hostname) |
|
48 |
publisher.app_dir = os.path.join(app_dir, hostname) |
|
49 |
cron_worker(publisher, now) |
|
50 |
if verbosity > 2: |
|
51 |
print('cron end (release lock %s)' % lockfile) |
|
52 |
except locket.LockError: |
|
53 |
if verbosity > 0: |
|
54 |
print('can not start cron job, locked by %s' % lockfile) |
|
41 |
- |