From b845580db31f108bfea1a8b0c187cfceec63d096 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 18 Jul 2020 13:19:09 +0200 Subject: [PATCH] stamina: add "smart" stream errors handling --- nonstop/management/commands/stamina.py | 51 ++++++++++++++++++- .../0029_scheduleddiffusion_auto_delayed.py | 20 ++++++++ nonstop/models.py | 4 ++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 nonstop/migrations/0029_scheduleddiffusion_auto_delayed.py diff --git a/nonstop/management/commands/stamina.py b/nonstop/management/commands/stamina.py index b604126..42c5df8 100644 --- a/nonstop/management/commands/stamina.py +++ b/nonstop/management/commands/stamina.py @@ -256,7 +256,56 @@ class Command(BaseCommand): if slot.jingle_id: await self.player_process(slot.jingle, timeout=60) logger.debug('Stream timeout: %s', (slot.end_datetime - now).total_seconds()) - await self.player_process(slot, timeout=(slot.end_datetime - now).total_seconds()) + short_interruption_counter = 0 + has_played = False + while True: + player_start_time = datetime.datetime.now() + await self.player_process(slot, timeout=(slot.end_datetime - player_start_time).total_seconds()) + now = datetime.datetime.now() + if (slot.end_datetime - now).total_seconds() < 2: + # it went well, stop + break + # stream got interrupted + if (datetime.datetime.now() - player_start_time).total_seconds() < 15: + # and was up for less than 15 seconds. + if not has_played: + # never up before, probably not even started + if isinstance(slot, RecurringStreamOccurence): + # no mercy for recurring stream, remove occurence + logger.info('Missing stream for %s, removing', slot) + slot.delete() + elif slot.auto_delayed is True: + # was already delayed and is still not up, remove. + logger.info('Still missing stream for %s, removing', slot) + slot.delete() + else: + # push back start datetime for 5 minutes, and get + # back to nonstop music in the meantime + logger.info('Pushing starting time of %s', slot.diffusion.episode) + slot.diffusion.datetime = slot.diffusion.datetime + datetime.timedelta(seconds=300) + slot.diffusion.episode.duration = slot.diffusion.episode.get_duration() - 5 + if slot.diffusion.episode.duration <= 5: + slot.diffusion.episode.duration = 0 + slot.auto_delayed = True + slot.diffusion.save() + slot.diffusion.episode.save() + slot.save() + break + short_interruption_counter += 1 + # wait a bit + await asyncio.sleep(short_interruption_counter) + else: + # mark stream as ok at least one, and reset short + # interruption counter + has_played = True + short_interruption_counter = 0 + logger.debug('Stream error for %s', slot) + + if short_interruption_counter > 5: + # many short interruptions + logger.info('Too many stream errors for %s, removing', slot) + slot.delete() + break else: if hasattr(slot, 'episode'): logger.info('Episode: %s (id: %s)', slot.episode, slot.episode.id) diff --git a/nonstop/migrations/0029_scheduleddiffusion_auto_delayed.py b/nonstop/migrations/0029_scheduleddiffusion_auto_delayed.py new file mode 100644 index 0000000..5012eee --- /dev/null +++ b/nonstop/migrations/0029_scheduleddiffusion_auto_delayed.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2020-07-18 13:18 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('nonstop', '0028_auto_20200716_1452'), + ] + + operations = [ + migrations.AddField( + model_name='scheduleddiffusion', + name='auto_delayed', + field=models.BooleanField(default=False), + ), + ] diff --git a/nonstop/models.py b/nonstop/models.py index a91a8ca..7563104 100644 --- a/nonstop/models.py +++ b/nonstop/models.py @@ -231,6 +231,7 @@ class ScheduledDiffusion(models.Model): stream = models.ForeignKey(Stream, null=True, blank=True) creation_timestamp = models.DateTimeField(auto_now_add=True, null=True) added_to_nonstop_timestamp = models.DateTimeField(null=True) + auto_delayed = models.BooleanField(default=False) def __str__(self): return 'Diffusion of %s' % self.diffusion @@ -324,6 +325,9 @@ class RecurringStreamOccurence(models.Model, RecurringOccurenceMixin): diffusion = models.ForeignKey(RecurringStreamDiffusion, on_delete=models.CASCADE) datetime = models.DateTimeField(_('Date/time'), db_index=True) + def __str__(self): + return 'Recurring stream of %s' % self.diffusion.stream + @property def stream(self): return self.diffusion.stream -- 2.39.2