Added status field to import batch, it's synced based on jobs
This commit is contained in:
parent
15bdf18705
commit
24e2555793
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
Loading…
Reference in New Issue