@@ -37,6 +37,7 @@ def create(request):
37
37
from django .core .paginator import Paginator , InvalidPage
38
38
from django .apps import apps
39
39
from django .db import transaction as tx
40
+ from django_pglocks import advisory_lock
40
41
41
42
from taiga .mdrender .service import render as mdrender
42
43
from taiga .base .utils .db import get_typename_for_model_class
@@ -269,6 +270,7 @@ def get_modified_fields(obj:object, last_modifications):
269
270
270
271
return modified_fields
271
272
273
+
272
274
@tx .atomic
273
275
def take_snapshot (obj :object , * , comment :str = "" , user = None , delete :bool = False ):
274
276
"""
@@ -280,56 +282,57 @@ def take_snapshot(obj:object, *, comment:str="", user=None, delete:bool=False):
280
282
"""
281
283
282
284
key = make_key_from_model_object (obj )
283
- typename = get_typename_for_model_class (obj .__class__ )
284
-
285
- new_fobj = freeze_model_instance (obj )
286
- old_fobj , need_real_snapshot = get_last_snapshot_for_key (key )
287
-
288
- entry_model = apps .get_model ("history" , "HistoryEntry" )
289
- user_id = None if user is None else user .id
290
- user_name = "" if user is None else user .get_full_name ()
291
-
292
- # Determine history type
293
- if delete :
294
- entry_type = HistoryType .delete
295
- elif new_fobj and not old_fobj :
296
- entry_type = HistoryType .create
297
- elif new_fobj and old_fobj :
298
- entry_type = HistoryType .change
299
- else :
300
- raise RuntimeError ("Unexpected condition" )
301
-
302
- fdiff = make_diff (old_fobj , new_fobj )
303
-
304
- # If diff and comment are empty, do
305
- # not create empty history entry
306
- if (not fdiff .diff and not comment
307
- and old_fobj is not None
308
- and entry_type != HistoryType .delete ):
309
-
310
- return None
311
-
312
- fvals = make_diff_values (typename , fdiff )
313
-
314
- if len (comment ) > 0 :
315
- is_hidden = False
316
- else :
317
- is_hidden = is_hidden_snapshot (fdiff )
318
-
319
- kwargs = {
320
- "user" : {"pk" : user_id , "name" : user_name },
321
- "key" : key ,
322
- "type" : entry_type ,
323
- "snapshot" : fdiff .snapshot if need_real_snapshot else None ,
324
- "diff" : fdiff .diff ,
325
- "values" : fvals ,
326
- "comment" : comment ,
327
- "comment_html" : mdrender (obj .project , comment ),
328
- "is_hidden" : is_hidden ,
329
- "is_snapshot" : need_real_snapshot ,
330
- }
331
-
332
- return entry_model .objects .create (** kwargs )
285
+ with advisory_lock (key ) as acquired_key_lock :
286
+ typename = get_typename_for_model_class (obj .__class__ )
287
+
288
+ new_fobj = freeze_model_instance (obj )
289
+ old_fobj , need_real_snapshot = get_last_snapshot_for_key (key )
290
+
291
+ entry_model = apps .get_model ("history" , "HistoryEntry" )
292
+ user_id = None if user is None else user .id
293
+ user_name = "" if user is None else user .get_full_name ()
294
+
295
+ # Determine history type
296
+ if delete :
297
+ entry_type = HistoryType .delete
298
+ elif new_fobj and not old_fobj :
299
+ entry_type = HistoryType .create
300
+ elif new_fobj and old_fobj :
301
+ entry_type = HistoryType .change
302
+ else :
303
+ raise RuntimeError ("Unexpected condition" )
304
+
305
+ fdiff = make_diff (old_fobj , new_fobj )
306
+
307
+ # If diff and comment are empty, do
308
+ # not create empty history entry
309
+ if (not fdiff .diff and not comment
310
+ and old_fobj is not None
311
+ and entry_type != HistoryType .delete ):
312
+
313
+ return None
314
+
315
+ fvals = make_diff_values (typename , fdiff )
316
+
317
+ if len (comment ) > 0 :
318
+ is_hidden = False
319
+ else :
320
+ is_hidden = is_hidden_snapshot (fdiff )
321
+
322
+ kwargs = {
323
+ "user" : {"pk" : user_id , "name" : user_name },
324
+ "key" : key ,
325
+ "type" : entry_type ,
326
+ "snapshot" : fdiff .snapshot if need_real_snapshot else None ,
327
+ "diff" : fdiff .diff ,
328
+ "values" : fvals ,
329
+ "comment" : comment ,
330
+ "comment_html" : mdrender (obj .project , comment ),
331
+ "is_hidden" : is_hidden ,
332
+ "is_snapshot" : need_real_snapshot ,
333
+ }
334
+
335
+ return entry_model .objects .create (** kwargs )
333
336
334
337
335
338
# High level query api
0 commit comments