2017-05-25 2 views
2

Je dois garder trace de la date à laquelle un utilisateur a été mentionné dans un post et mettre à jour ce champ chaque fois qu'un nouveau message est créé en fonction de son heure de publication.Comment éviter les conditions de concurrence dans la mise à jour du champ de modèle à l'horodatage le plus récent

Mon code actuel ressemble à ceci:

from django.db.models.signals import post_save 
from django.dispatch import receiver 
from messageboard.models import Post 

@receiver(post_save, sender=Post) 
def user_last_mentioned_updater(sender, instance, **kwargs): 
    for users in instance.mentions: 
     user.last_mentioned = max(user.last_mentioned, instance.timestamp) 
     user.save() 

Toutefois, si deux postes sont traités en même temps, cela pourrait laisser le champ last_mentioned à l'horodatage du précédent post.

Malheureusement, F ne supporte pas la, opération max quand je l'essayer je reçois un TypeError: unorderable types: datetime.datetime() > F():

user.last_mentioned = max(F('last_mentioned'), instance.timestamp) 

Comment puis-je éviter cette condition de course?

Si cela est important, j'utilise pour le moment Postgresql pour l'ORM, bien que cela puisse changer.

Répondre

2

est ici une version qui devrait être libre de conditions de course et plus efficace:

@receiver(post_save, sender=Post) 
def user_last_mentioned_updater(sender, instance, **kwargs) 
    User.objects.filter(
     id__in=[u.id for u in instance.mentions], 
     last_mentioned__lt=instance.timestamp, 
    ).update(last_mentioned=instance.timestamp) 

C'est, nous sélectionnons les utilisateurs mentionnés qui est horodatages ont besoin de mise à jour, et les mettre à jour, le tout dans une seule instruction SQL.

+0

Merci, cela a parfaitement fonctionné. – AJMansfield