Completed
Pull Request — master (#41)
by Paolo
06:52
created

common.tasks   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 76
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 8
eloc 40
dl 0
loc 76
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A BatchUpdateMixin.batch_update() 0 19 5

1 Function

Rating   Name   Duplication   Size   Complexity  
A redis_lock() 0 24 3
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 submissions.helpers import send_message
17
from validation.helpers import construct_validation_message
18
from common.constants import NEED_REVISION
19
20
# Lock expires in 10 minutes
21
LOCK_EXPIRE = 60 * 10
22
23
24
class BatchUpdateMixin:
25
    """Mixin to do batch update of fields to fix validation"""
26
27
    item_cls = None
28
    submission_cls = None
29
30
    def batch_update(self, submission_id, ids, attribute):
31
        for id_, value in ids.items():
32
            if value == '' or value == 'None':
33
                value = None
34
35
            item_object = self.item_cls.objects.get(pk=id_)
36
37
            if getattr(item_object, attribute) != value:
38
                setattr(item_object, attribute, value)
39
                item_object.save()
40
41
        # Update submission
42
        submission_obj = self.submission_cls.objects.get(pk=submission_id)
43
        submission_obj.status = NEED_REVISION
44
        submission_obj.message = "Data updated, try to rerun validation"
45
        submission_obj.save()
46
47
        send_message(
48
            submission_obj, construct_validation_message(submission_obj)
49
        )
50
51
52
@contextmanager
53
def redis_lock(lock_id, blocking=False):
54
    # read parameters from settings
55
    REDIS_CLIENT = redis.StrictRedis(
56
        host=settings.REDIS_HOST,
57
        port=settings.REDIS_PORT,
58
        db=settings.REDIS_DB)
59
60
    timeout_at = monotonic() + LOCK_EXPIRE - 3
61
62
    lock = REDIS_CLIENT.lock(lock_id, timeout=LOCK_EXPIRE)
63
    status = lock.acquire(blocking=blocking)
64
65
    try:
66
        yield status
67
68
    finally:
69
        # we take advantage of using add() for atomic locking
70
        if monotonic() < timeout_at and status:
71
            # don't release the lock if we exceeded the timeout
72
            # to lessen the chance of releasing an expired lock
73
            # owned by someone else
74
            # also don't release the lock if we didn't acquire it
75
            lock.release()
76