Passed
Pull Request — master (#41)
by
unknown
06:08
created

common.tasks.BatchUpdateMixin.batch_update()   D

Complexity

Conditions 13

Size

Total Lines 31
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 31
rs 4.2
c 0
b 0
f 0
cc 13
nop 5

How to fix   Complexity   

Complexity

Complex classes like common.tasks.BatchUpdateMixin.batch_update() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Tue Jan 15 16:42:24 2019
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import redis
10
11
from contextlib import contextmanager
12
from celery.five import monotonic
13
14
from django.conf import settings
15
16
from image_app.models import Submission, Sample, Animal, DictUberon, \
17
    DictDevelStage, DictPhysioStage, DictSex, DictSpecie
18
from submissions.helpers import send_message
19
from validation.helpers import construct_validation_message
20
from common.constants import NEED_REVISION
21
22
# Lock expires in 10 minutes
23
LOCK_EXPIRE = 60 * 10
24
25
26
class BatchUpdateMixin:
27
    """Mixin to do batch update of fields to fix validation"""
28
29
    def batch_update(self, submission_id, ids, attribute, item_type):
30
        for id, value in ids.items():
31
            if value == '' or value == 'None':
32
                value = None
33
            if item_type == 'sample':
34
                item_object = Sample.objects.get(pk=id)
35
            elif item_type == 'animal':
36
                item_object = Animal.objects.get(pk=id)
37
            elif item_type == 'dictuberon':
38
                item_object = DictUberon.objects.get(pk=id)
39
            elif item_type == 'dictdevelstage':
40
                item_object = DictDevelStage.objects.get(pk=id)
41
            elif item_type == 'dictphysiostage':
42
                item_object = DictPhysioStage.objects.get(pk=id)
43
            elif item_type == 'dictsex':
44
                item_object = DictSex.objects.get(pk=id)
45
            elif item_type == 'dictspecie_animal' or \
46
                    item_type == 'dictspecie_sample':
47
                item_object = DictSpecie.objects.get(pk=id)
48
            if getattr(item_object, attribute) != value:
0 ignored issues
show
introduced by
The variable item_object does not seem to be defined for all execution paths.
Loading history...
49
                setattr(item_object, attribute, value)
50
                item_object.save()
51
52
        # Update submission
53
        submission_obj = Submission.objects.get(pk=submission_id)
54
        submission_obj.status = NEED_REVISION
55
        submission_obj.message = "Data updated, try to rerun validation"
56
        submission_obj.save()
57
58
        send_message(
59
            submission_obj, construct_validation_message(submission_obj)
60
        )
61
62
63
@contextmanager
64
def redis_lock(lock_id, blocking=False):
65
    # read parameters from settings
66
    REDIS_CLIENT = redis.StrictRedis(
67
        host=settings.REDIS_HOST,
68
        port=settings.REDIS_PORT,
69
        db=settings.REDIS_DB)
70
71
    timeout_at = monotonic() + LOCK_EXPIRE - 3
72
73
    lock = REDIS_CLIENT.lock(lock_id, timeout=LOCK_EXPIRE)
74
    status = lock.acquire(blocking=blocking)
75
76
    try:
77
        yield status
78
79
    finally:
80
        # we take advantage of using add() for atomic locking
81
        if monotonic() < timeout_at and status:
82
            # don't release the lock if we exceeded the timeout
83
            # to lessen the chance of releasing an expired lock
84
            # owned by someone else
85
            # also don't release the lock if we didn't acquire it
86
            lock.release()
87