Projet

Général

Profil

0001-dataviz-update-statistics-list-every-5-minutes-50892.patch

Valentin Deniaud, 10 février 2021 10:24

Télécharger (9,2 ko)

Voir les différences:

Subject: [PATCH] dataviz: update statistics list every 5 minutes (#50892)

 combo/apps/dataviz/__init__.py                | 49 +-------------
 .../commands/update_available_statistics.py   | 66 +++++++++++++++++++
 debian/combo.cron.d                           |  1 +
 tests/test_dataviz.py                         | 13 ++--
 4 files changed, 75 insertions(+), 54 deletions(-)
 create mode 100644 combo/apps/dataviz/management/commands/update_available_statistics.py
combo/apps/dataviz/__init__.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import django.apps
18
from django.core import checks
19
from django.conf import settings
20
from django.utils import timezone
21 18
from django.utils.translation import ugettext_lazy as _
22 19

  
23
from combo.utils import requests
24 20

  
25 21

  
26 22
class AppConfig(django.apps.AppConfig):
......
32 28
        return urls.urlpatterns
33 29

  
34 30
    def hourly(self):
35
        self.update_available_statistics()
36

  
37
    def update_available_statistics(self):
38
        from .models import Statistic, ChartNgCell
39
        if not settings.KNOWN_SERVICES:
40
            return
41

  
42
        start_update = timezone.now()
43
        for provider in settings.STATISTICS_PROVIDERS:
44
            if isinstance(provider, dict):
45
                url = provider['url']
46
                sites = {provider['id']: {'title': provider['name']}}
47
                provider = provider['id']
48
            else:
49
                sites = settings.KNOWN_SERVICES.get(provider, {})
50
                url = '/visualization/json/' if provider == 'bijoe' else '/api/statistics/'
51

  
52
            for site_key, site_dict in sites.items():
53
                site_title = site_dict.pop('title', '')
54
                response = requests.get(
55
                    url, remote_service=site_dict, without_user=True, headers={'accept': 'application/json'}
56
                )
57
                if response.status_code != 200:
58
                    continue
59

  
60
                result = response.json()
61
                if isinstance(result, dict):
62
                    result = result['data']  # detect new api
63

  
64
                for stat in result:
65
                    Statistic.objects.update_or_create(
66
                        slug=stat.get('slug') or stat['id'],
67
                        site_slug=site_key,
68
                        service_slug=provider,
69
                        defaults={
70
                            'label': stat['name'],
71
                            'url': stat.get('data-url') or stat['url'],
72
                            'site_title': site_title,
73
                            'filters': stat.get('filters', []),
74
                            'available': True,
75
                        }
76
                    )
77
        Statistic.objects.filter(last_update__lt=start_update).update(available=False)
78

  
31
        from combo.apps.dataviz.models import ChartNgCell
79 32
        for cell in ChartNgCell.objects.all():
80 33
            cell.check_validity()
81 34

  
combo/apps/dataviz/management/commands/update_available_statistics.py
1
# combo - content management system
2
# Copyright (C) 2021  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.conf import settings
18
from django.core.management.base import BaseCommand
19
from django.utils import timezone
20

  
21
from combo.apps.dataviz.models import Statistic
22
from combo.utils import requests
23

  
24

  
25
class Command(BaseCommand):
26

  
27
    def handle(self, *args, **kwargs):
28
        if not settings.KNOWN_SERVICES:
29
            return
30

  
31
        start_update = timezone.now()
32
        for provider in settings.STATISTICS_PROVIDERS:
33
            if isinstance(provider, dict):
34
                url = provider['url']
35
                sites = {provider['id']: {'title': provider['name']}}
36
                provider = provider['id']
37
            else:
38
                sites = settings.KNOWN_SERVICES.get(provider, {})
39
                url = '/visualization/json/' if provider == 'bijoe' else '/api/statistics/'
40

  
41
            for site_key, site_dict in sites.items():
42
                site_title = site_dict.pop('title', '')
43
                response = requests.get(
44
                    url, remote_service=site_dict, timeout=5, without_user=True, headers={'accept': 'application/json'}
45
                )
46
                if response.status_code != 200:
47
                    continue
48

  
49
                result = response.json()
50
                if isinstance(result, dict):
51
                    result = result['data']  # detect new api
52

  
53
                for stat in result:
54
                    Statistic.objects.update_or_create(
55
                        slug=stat.get('slug') or stat['id'],
56
                        site_slug=site_key,
57
                        service_slug=provider,
58
                        defaults={
59
                            'label': stat['name'],
60
                            'url': stat.get('data-url') or stat['url'],
61
                            'site_title': site_title,
62
                            'filters': stat.get('filters', []),
63
                            'available': True,
64
                        }
65
                    )
66
        Statistic.objects.filter(last_update__lt=start_update).update(available=False)
debian/combo.cron.d
1 1
MAILTO=root
2 2

  
3 3
0 8 * * * combo /usr/bin/combo-manage tenant_command notify_new_remote_invoices --all-tenants -v0
4
*/5 * * * * combo /usr/bin/combo-manage tenant_command update_available_statistics --all-tenants -v0
tests/test_dataviz.py
9 9

  
10 10
from django.apps import apps
11 11
from django.contrib.auth.models import User, Group
12
from django.core.management import call_command
12 13
from django.db import connection
13 14
from django.db.migrations.executor import MigrationExecutor
14 15
from django.test import override_settings
......
323 324
    }
324 325
    settings.STATISTICS_PROVIDERS = ['bijoe']
325 326
    appconfig = apps.get_app_config('dataviz')
326
    appconfig.hourly()
327
    call_command('update_available_statistics')
327 328
    assert Statistic.objects.count() == len(VISUALIZATION_JSON)
328 329

  
329 330

  
......
342 343
    }
343 344
    settings.STATISTICS_PROVIDERS = ['authentic']
344 345
    appconfig = apps.get_app_config('dataviz')
345
    appconfig.hourly()
346
    call_command('update_available_statistics')
346 347
    assert Statistic.objects.count() == len(STATISTICS_LIST['data'])
347 348

  
348 349

  
......
1112 1113

  
1113 1114
    appconfig = apps.get_app_config('dataviz')
1114 1115
    with HTTMock(bijoe_mock_unavailable):
1115
        appconfig.hourly()
1116
        call_command('update_available_statistics')
1116 1117
    assert Statistic.objects.filter(available=True).count() == all_stats_count - 2
1117 1118

  
1118 1119

  
......
1165 1166

  
1166 1167
    appconfig = apps.get_app_config('dataviz')
1167 1168
    with HTTMock(server_error):
1168
        appconfig.hourly()
1169
        call_command('update_available_statistics')
1169 1170
    assert Statistic.objects.count() == statistics_count
1170 1171

  
1171 1172
    @urlmatch(scheme='https', netloc=r'stat.com', path='/stats/')
......
1173 1174
        return {'content': json.dumps(catalog), 'status_code': 200}
1174 1175

  
1175 1176
    with HTTMock(success):
1176
        appconfig.hourly()
1177
        call_command('update_available_statistics')
1177 1178

  
1178 1179
    assert Statistic.objects.count() == statistics_count + 1
1179 1180
    statistic = Statistic.objects.get(slug='test')
......
1187 1188
    settings.STATISTICS_PROVIDERS.append('unknown')
1188 1189
    appconfig = apps.get_app_config('dataviz')
1189 1190
    with HTTMock(success):
1190
        appconfig.hourly()  # unknown provider is ignored
1191
        call_command('update_available_statistics')  # unknown provider is ignored
1191 1192

  
1192 1193

  
1193 1194
@with_httmock(new_api_mock)
1194
-