Projet

Général

Profil

0001-don-t-start-a-new-cron-if-locked-18519.patch

Thomas Noël, 23 mars 2018 18:50

Télécharger (4,45 ko)

Voir les différences:

Subject: [PATCH] don't start a new cron if locked (#18519)

 tests/test_publisher.py                | 29 +++++++++++++++++++++++++++++
 wcs/qommon/management/commands/cron.py | 32 +++++++++++++++++++++-----------
 2 files changed, 50 insertions(+), 11 deletions(-)
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
            with pytest.raises(CommandError, match='can not start cron job, locked'):
187
                call_command('cron', verbosity=1)  # CommandError with verbosity>0
188
            assert cron_worker.call_count == 0
189
    # verify that the lock is released
190
    with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker:
191
        call_command('cron')
192
        assert cron_worker.call_count == 1
193

  
194
    # simulate a cron crash
195
    with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker:
196
        cron_worker.side_effect = NotImplementedError
197
        with pytest.raises(NotImplementedError):
198
            call_command('cron')
199
        assert cron_worker.call_count == 1
200
    # verify that the lock is released
201
    with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker:
202
        call_command('cron')
203
        assert cron_worker.call_count == 1
wcs/qommon/management/commands/cron.py
18 18
import time
19 19
import os
20 20

  
21
from django.core.management.base import BaseCommand
21
from django.core.management.base import BaseCommand, CommandError
22 22
from qommon.publisher import get_publisher_class
23 23

  
24
from qommon import get_logger, get_publisher
24 25
from qommon.vendor import locket
25 26
from qommon.cron import cron_worker
26 27

  
......
28 29
class Command(BaseCommand):
29 30
    help = 'Execute cronjobs'
30 31

  
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)
32
    def add_arguments(self, parser):
33
        super(Command, self).add_arguments(parser)
34
        parser.set_defaults(verbosity=0)
35

  
36
    def handle(self, verbosity, **kwargs):
37
        lockfile = os.path.join(tempfile.gettempdir(), 'wcs-cron-in-progress.lock')
38
        try:
39
            with locket.lock_file(lockfile, timeout=0):
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
                    publisher.app_dir = os.path.join(app_dir, hostname)
47
                    cron_worker(publisher, now)
48
        except locket.LockError:
49
            if verbosity > 0:
50
                raise CommandError('can not start cron job, locked by %s' % lockfile)
41
-