Skip to content

Commit 44a4920

Browse files
k9845frozenhelium
authored andcommitted
Add optimistic lock in dref
1 parent cb01eca commit 44a4920

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 3.2.16 on 2022-10-18 07:32
2+
3+
import datetime
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('dref', '0043_delete_dreffileupload'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='dref',
16+
name='modified_at',
17+
field=models.DateTimeField(blank=True, default=datetime.datetime.now, verbose_name='modified at'),
18+
),
19+
]

dref/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import reversion
22
import os
33
import copy
4+
from datetime import datetime
45

56
from pdf2image import convert_from_bytes
67

@@ -227,7 +228,10 @@ class Status(models.IntegerChoices):
227228
COMPLETED = 1, _('Completed')
228229

229230
created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True)
230-
modified_at = models.DateTimeField(verbose_name=_('modified at'), auto_now=True)
231+
modified_at = models.DateTimeField(
232+
verbose_name=_('modified at'),
233+
default=datetime.now, blank=True
234+
)
231235
created_by = models.ForeignKey(
232236
settings.AUTH_USER_MODEL, verbose_name=_('created by'), on_delete=models.SET_NULL,
233237
null=True, related_name='created_by_dref'

dref/serializers.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ def create(self, validated_data):
349349
def update(self, instance, validated_data):
350350
validated_data['modified_by'] = self.context['request'].user
351351
is_assessment_report = validated_data.get('is_assessment_report')
352+
modified_at = validated_data.get('modified_at')
352353
if is_assessment_report:
353354
# Previous Operations
354355
validated_data['lessons_learned'] = None
@@ -374,18 +375,21 @@ def update(self, instance, validated_data):
374375
dref_assessment_report = super().update(instance, validated_data)
375376
dref_assessment_report.needs_identified.clear()
376377
return dref_assessment_report
378+
377379
# we don't send notification again to the already notified users:
378380
if 'users' in validated_data:
379381
to = {u.email for u in validated_data['users']
380382
if u.email not in {t.email for t in instance.users.iterator()}}
381383
else:
382384
to = None
383-
dref = super().update(instance, validated_data)
384-
if to:
385-
transaction.on_commit(
386-
lambda: send_dref_email.delay(dref.id, list(to), 'Updated')
387-
)
388-
return dref
385+
if modified_at and instance.modified_at and modified_at > instance.modified_at:
386+
dref = super().update(instance, validated_data)
387+
if to:
388+
transaction.on_commit(
389+
lambda: send_dref_email.delay(dref.id, list(to), 'Updated')
390+
)
391+
return dref
392+
return instance
389393

390394

391395
class DrefOperationalUpdateSerializer(

dref/test_views.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
from unittest import mock
3+
from datetime import datetime
34

45

56
from django.conf import settings
@@ -847,3 +848,27 @@ def test_dref_for_super_user(self):
847848
response = self.client.get(url)
848849
self.assertEqual(response.status_code, 200)
849850
self.assertEqual(len(response.data['results']), 0)
851+
852+
def test_dref_latest_update(self):
853+
dref = DrefFactory.create(
854+
title='Test Title',
855+
created_by=self.user,
856+
modified_at=datetime(2022, 4, 18, 2, 29, 39, 793615)
857+
)
858+
url = f'/api/v2/dref/{dref.id}/'
859+
data = {
860+
'title': "New title",
861+
'modified_at': datetime(2022, 2, 18, 2, 29, 39, 793615),
862+
}
863+
864+
self.client.force_authenticate(self.user)
865+
response = self.client.patch(url, data=data)
866+
self.assertEqual(response.status_code, 200)
867+
# Title should be same since modified_at is less than modified_at in database
868+
self.assertEqual(response.data['title'], "Test Title")
869+
870+
data['modified_at'] = datetime.now()
871+
response = self.client.patch(url, data=data)
872+
self.assertEqual(response.status_code, 200)
873+
# Title should be latest since modified_at is greater than modified_at in database
874+
self.assertEqual(response.data['title'], "New title")

0 commit comments

Comments
 (0)