kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
				
				
				
			Added status field to import batch, it's synced based on jobs
							rodzic
							
								
									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.core.files.base import ContentFile
 | 
			
		||||
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.utils import timezone
 | 
			
		||||
 | 
			
		||||
from taggit.managers import TaggableManager
 | 
			
		||||
from versatileimagefield.fields import VersatileImageField
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -400,6 +403,14 @@ class TrackFile(models.Model):
 | 
			
		|||
            self.mimetype = utils.guess_mimetype(self.audio_file)
 | 
			
		||||
        return super().save(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
IMPORT_STATUS_CHOICES = (
 | 
			
		||||
    ('pending', 'Pending'),
 | 
			
		||||
    ('finished', 'Finished'),
 | 
			
		||||
    ('errored', 'Errored'),
 | 
			
		||||
    ('skipped', 'Skipped'),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
class ImportBatch(models.Model):
 | 
			
		||||
    IMPORT_BATCH_SOURCES = [
 | 
			
		||||
        ('api', 'api'),
 | 
			
		||||
| 
						 | 
				
			
			@ -412,22 +423,24 @@ class ImportBatch(models.Model):
 | 
			
		|||
        'users.User',
 | 
			
		||||
        related_name='imports',
 | 
			
		||||
        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:
 | 
			
		||||
        ordering = ['-creation_date']
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return str(self.pk)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def status(self):
 | 
			
		||||
        pending = any([job.status == 'pending' for job in self.jobs.all()])
 | 
			
		||||
        errored = any([job.status == 'errored' for job in self.jobs.all()])
 | 
			
		||||
        if pending:
 | 
			
		||||
            return 'pending'
 | 
			
		||||
        if errored:
 | 
			
		||||
            return 'errored'
 | 
			
		||||
        return 'finished'
 | 
			
		||||
    def update_status(self):
 | 
			
		||||
        self.status = utils.compute_status(self.jobs.all())
 | 
			
		||||
        self.save(update_fields=['status'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ImportJob(models.Model):
 | 
			
		||||
    batch = models.ForeignKey(
 | 
			
		||||
| 
						 | 
				
			
			@ -440,13 +453,9 @@ class ImportJob(models.Model):
 | 
			
		|||
        on_delete=models.CASCADE)
 | 
			
		||||
    source = models.CharField(max_length=500)
 | 
			
		||||
    mbid = models.UUIDField(editable=False, null=True, blank=True)
 | 
			
		||||
    STATUS_CHOICES = (
 | 
			
		||||
        ('pending', 'Pending'),
 | 
			
		||||
        ('finished', 'Finished'),
 | 
			
		||||
        ('errored', 'Errored'),
 | 
			
		||||
        ('skipped', 'Skipped'),
 | 
			
		||||
    )
 | 
			
		||||
    status = models.CharField(choices=STATUS_CHOICES, default='pending', max_length=30)
 | 
			
		||||
 | 
			
		||||
    status = models.CharField(
 | 
			
		||||
        choices=IMPORT_STATUS_CHOICES, default='pending', max_length=30)
 | 
			
		||||
    audio_file = models.FileField(
 | 
			
		||||
        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):
 | 
			
		||||
    b = min(100000, f.size)
 | 
			
		||||
    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()
 | 
			
		||||
    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', [
 | 
			
		||||
    ('ogg', 'audio/ogg'),
 | 
			
		||||
    ('mp3', 'audio/mpeg'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue