Added status field to import batch, it's synced based on jobs

merge-requests/154/head
Eliot Berriot 2018-02-21 00:02:09 +01:00
rodzic 15bdf18705
commit 24e2555793
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: DD6965E2476E5C27
5 zmienionych plików z 97 dodań i 17 usunięć

Wyświetl plik

@ -0,0 +1,18 @@
# Generated by Django 2.0.2 on 2018-02-20 19:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('music', '0019_populate_mimetypes'),
]
operations = [
migrations.AddField(
model_name='importbatch',
name='status',
field=models.CharField(choices=[('pending', 'Pending'), ('finished', 'Finished'), ('errored', 'Errored'), ('skipped', 'Skipped')], default='pending', max_length=30),
),
]

Wyświetl plik

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
from django.db import migrations, models
def populate_status(apps, schema_editor):
from funkwhale_api.music.utils import compute_status
ImportBatch = apps.get_model("music", "ImportBatch")
for ib in ImportBatch.objects.prefetch_related('jobs'):
ib.status = compute_status(ib.jobs.all())
ib.save(update_fields=['status'])
def rewind(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('music', '0020_importbatch_status'),
]
operations = [
migrations.RunPython(populate_status, rewind),
]

Wyświetl plik

@ -10,8 +10,11 @@ from django.conf import settings
from django.db import models from django.db import models
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.files import File from django.core.files import File
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
from versatileimagefield.fields import VersatileImageField from versatileimagefield.fields import VersatileImageField
@ -400,6 +403,14 @@ class TrackFile(models.Model):
self.mimetype = utils.guess_mimetype(self.audio_file) self.mimetype = utils.guess_mimetype(self.audio_file)
return super().save(**kwargs) return super().save(**kwargs)
IMPORT_STATUS_CHOICES = (
('pending', 'Pending'),
('finished', 'Finished'),
('errored', 'Errored'),
('skipped', 'Skipped'),
)
class ImportBatch(models.Model): class ImportBatch(models.Model):
IMPORT_BATCH_SOURCES = [ IMPORT_BATCH_SOURCES = [
('api', 'api'), ('api', 'api'),
@ -412,22 +423,24 @@ class ImportBatch(models.Model):
'users.User', 'users.User',
related_name='imports', related_name='imports',
on_delete=models.CASCADE) on_delete=models.CASCADE)
status = models.CharField(
choices=IMPORT_STATUS_CHOICES, default='pending', max_length=30)
import_request = models.ForeignKey(
'requests.ImportRequest',
related_name='import_batches',
null=True,
blank=True,
on_delete=models.CASCADE)
class Meta: class Meta:
ordering = ['-creation_date'] ordering = ['-creation_date']
def __str__(self): def __str__(self):
return str(self.pk) return str(self.pk)
@property def update_status(self):
def status(self): self.status = utils.compute_status(self.jobs.all())
pending = any([job.status == 'pending' for job in self.jobs.all()]) self.save(update_fields=['status'])
errored = any([job.status == 'errored' for job in self.jobs.all()])
if pending:
return 'pending'
if errored:
return 'errored'
return 'finished'
class ImportJob(models.Model): class ImportJob(models.Model):
batch = models.ForeignKey( batch = models.ForeignKey(
@ -440,13 +453,9 @@ class ImportJob(models.Model):
on_delete=models.CASCADE) on_delete=models.CASCADE)
source = models.CharField(max_length=500) source = models.CharField(max_length=500)
mbid = models.UUIDField(editable=False, null=True, blank=True) mbid = models.UUIDField(editable=False, null=True, blank=True)
STATUS_CHOICES = (
('pending', 'Pending'), status = models.CharField(
('finished', 'Finished'), choices=IMPORT_STATUS_CHOICES, default='pending', max_length=30)
('errored', 'Errored'),
('skipped', 'Skipped'),
)
status = models.CharField(choices=STATUS_CHOICES, default='pending', max_length=30)
audio_file = models.FileField( audio_file = models.FileField(
upload_to='imports/%Y/%m/%d', max_length=255, null=True, blank=True) upload_to='imports/%Y/%m/%d', max_length=255, null=True, blank=True)

Wyświetl plik

@ -43,3 +43,13 @@ def get_query(query_string, search_fields):
def guess_mimetype(f): def guess_mimetype(f):
b = min(100000, f.size) b = min(100000, f.size)
return magic.from_buffer(f.read(b), mime=True) return magic.from_buffer(f.read(b), mime=True)
def compute_status(jobs):
errored = any([job.status == 'errored' for job in jobs])
if errored:
return 'errored'
pending = any([job.status == 'pending' for job in jobs])
if pending:
return 'pending'
return 'finished'

Wyświetl plik

@ -52,6 +52,20 @@ def test_import_job_is_bound_to_track_file(factories, mocker):
job.refresh_from_db() job.refresh_from_db()
assert job.track_file.track == track assert job.track_file.track == track
@pytest.mark.parametrize('status', ['pending', 'errored', 'finished'])
def test_saving_job_updates_batch_status(status,factories, mocker):
batch = factories['music.ImportBatch']()
assert batch.status == 'pending'
job = factories['music.ImportJob'](batch=batch, status=status)
batch.refresh_from_db()
assert batch.status == status
@pytest.mark.parametrize('extention,mimetype', [ @pytest.mark.parametrize('extention,mimetype', [
('ogg', 'audio/ogg'), ('ogg', 'audio/ogg'),
('mp3', 'audio/mpeg'), ('mp3', 'audio/mpeg'),