Projet

Général

Profil

0001-ovh-retry-on-too-many-requests-error-44730.patch

Nicolas Roche, 03 septembre 2021 10:23

Télécharger (5,67 ko)

Voir les différences:

Subject: [PATCH] ovh: retry on too many requests error (#44730)

 passerelle/apps/ovh/models.py |  3 +++
 passerelle/sms/views.py       |  3 ++-
 tests/test_sms.py             | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 1 deletion(-)
passerelle/apps/ovh/models.py
9 9
from django.contrib.postgres.fields import ArrayField
10 10
from django.core.mail import send_mail
11 11
from django.db import models
12 12
from django.template.loader import render_to_string
13 13
from django.utils import timezone
14 14
from django.utils.encoding import force_text
15 15
from django.utils.translation import ugettext_lazy as _
16 16

  
17
from passerelle.base.models import SkipJob
17 18
from passerelle.sms.models import SMSResource
18 19
from passerelle.utils.jsonresponse import APIError
19 20

  
20 21

  
21 22
class OVHSMSGateway(SMSResource):
22 23
    documentation_url = (
23 24
        'https://doc-publik.entrouvert.com/admin-fonctionnel/les-tutos/configuration-envoi-sms/'
24 25
    )
......
275 276
                            self.slug,
276 277
                            credit_left,
277 278
                            self.credit_threshold_alert,
278 279
                        )
279 280
                    ret['credit_left'] = credit_left
280 281
                    ret['ovh_result'] = result
281 282
                    ret['sms_ids'] = result.get('SmsIds', [])
282 283
                    return ret
284
                elif result['status'] == 429:
285
                    raise SkipJob(after_timestamp=3)
283 286
                else:
284 287
                    raise APIError('OVH error: %r' % result)
passerelle/sms/views.py
4 4
from django.contrib import messages
5 5
from django.db.models import Count
6 6
from django.db.models.functions import TruncDay
7 7
from django.http import JsonResponse
8 8
from django.utils.timezone import make_aware
9 9
from django.utils.translation import ugettext_lazy as _
10 10
from django.views.generic import FormView, View
11 11

  
12
from passerelle.base.models import SkipJob
12 13
from passerelle.utils.jsonresponse import APIError
13 14
from passerelle.views import GenericConnectorMixin
14 15

  
15 16
from .forms import SmsTestSendForm
16 17
from .models import SMSLog
17 18

  
18 19

  
19 20
class SmsTestSendView(GenericConnectorMixin, FormView):
......
33 34
        number = form.cleaned_data['number']
34 35
        sender = form.cleaned_data['sender']
35 36
        message = form.cleaned_data['message']
36 37
        connector = self.get_object()
37 38
        try:
38 39
            number = connector.clean_numbers([number])[0]
39 40
            number = connector.authorize_numbers([number])[0][0]
40 41
            connector.send_msg(text=message, sender=sender, destinations=[number], stop=False)
41
        except APIError as exc:
42
        except (APIError, SkipJob) as exc:
42 43
            messages.error(self.request, _('Sending SMS fails: %s' % exc))
43 44
        else:
44 45
            messages.success(self.request, _('An SMS was just sent'))
45 46
        return super(SmsTestSendView, self).form_valid(form)
46 47

  
47 48

  
48 49
class SmsStatisticsView(View):
49 50
    def get(self, request, *args, **kwargs):
tests/test_sms.py
173 173
            assert test_vector['result']['err_desc'] in job.status_details['error_summary']
174 174
            nb_failed += 1
175 175
        else:
176 176
            assert job.status == 'completed'
177 177
    assert Job.objects.filter(method_name='send_job').count() == total
178 178
    assert SMSLog.objects.count() == total - nb_failed
179 179

  
180 180

  
181
@pytest.mark.parametrize('connector', [OVHSMSGateway], indirect=True)
182
def test_sms_legacy_retry_after_error(app, connector, freezer):
183
    path = '/%s/%s/send/' % (connector.get_connector_slug(), connector.slug)
184
    assert not SMSLog.objects.filter(appname=connector.get_connector_slug(), slug=connector.slug).exists()
185

  
186
    payload = {
187
        'message': 'plop',
188
        'from': '+33699999999',
189
        'to': ['+33688888888'],
190
    }
191
    freezer.move_to('2019-01-01 00:00:00')
192
    result = app.post_json(path, params=payload)
193
    assert result.json['err'] == 0
194
    assert Job.objects.exists()
195
    assert Job.objects.get().status == 'registered'
196
    assert not Job.objects.get().after_timestamp
197
    with utils.mock_url(
198
        url=connector.URL,
199
        response={'status': 429, 'message': 'Too much requests.\nPlease retry in 3 seconds.'},
200
    ):
201
        connector.jobs()
202
    assert Job.objects.get().status == 'registered'
203
    assert Job.objects.get().after_timestamp
204

  
205
    with utils.mock_url(url=connector.URL, response={'status': 100, 'credit_left': 22}):
206
        connector.jobs()
207
    assert Job.objects.get().status == 'registered'
208

  
209
    freezer.move_to('2019-01-01 00:00:04')
210
    with utils.mock_url(url=connector.URL, response={'status': 100, 'creditLeft': 22}):
211
        connector.jobs()
212
    assert Job.objects.get().status == 'completed'
213
    assert SMSLog.objects.exists()
214

  
215

  
181 216
def test_manage_views(admin_user, app, connector):
182 217
    url = '/%s/%s/' % (connector.get_connector_slug(), connector.slug)
183 218
    resp = app.get(url)
184 219
    assert 'Endpoints' in resp.text
185 220
    assert not 'accessright/add' in resp.text
186 221
    app = login(app)
187 222
    resp = app.get(url)
188 223
    description_fields = [
189
-