2010-11-20 3 views
2

Les lignes de code suivantes illustrent un modèle de travail distribué que j'utilise pour croquer des données. Les tâches sont créées dans une base de données, leurs données sont stockées sur les disques durs et, une fois que toutes les informations sont disponibles, le statut du travail est défini sur "ATTENTE". De là, plusieurs travailleurs actifs entrent en jeu: de temps en temps, chacun d'entre eux émet une requête, dans laquelle il tente de «revendiquer» un travail. Afin de synchroniser les revendications, les requêtes sont encapsulées dans une transaction qui modifie immédiatement l'état du travail si la requête renvoie un candidat. Jusqu'ici tout va bien.Éviter la mise en cache de QuerySet django dans une méthode @static

Le problème est que l'appel à réclamer ne fonctionne que la première fois. En lisant QuerySets et leur comportement de mise en cache, il me semble que combiner les méthodes statiques et la mise en cache QuerySet revient toujours sur le cache ... voyez par vous-même:

J'ai une classe dérivée de django.db.models.Model :

class Job(models.Model): 
[...] 

dans lequel je définir la fonction statique suivant.

@staticmethod 
@transaction.commit_on_success 
def claim(): 
    # select the oldest, top priority job and 
    # update its record 
    jobs = Job.objects.filter(state__exact = 'WAITING').order_by('-priority', 'create_timestamp') 
    if jobs.count() > 0: 
     j = jobs[0] 
     j.state = 'CLAIMED' 
     j.save() 
     logger.info('Job::claim: claimed %s' % j.name) 
     return j 
    return None 

Y at-il une chose évidente que je fais mal? Quelle serait la meilleure façon de gérer cela? Comment puis-je m'assurer que le QuerySet ne met pas en cache ses résultats à travers différentes invocations de la méthode statique? Ou est-ce que j'ai raté quelque chose et poursuivi un fantôme? Toute aide serait grandement appréciée, merci!

Répondre

0

Pourquoi ne pas simplement avoir une fonction au niveau du module claim_jobs() qui lancerait la requête?

def claim_jobs(): 

    jobs = Job.objects.filter(...) 
    ... etc. 
+0

Mmh. Mauvais design - la méthode statique appartient vraiment à la classe. – Marc

+0

dépend de la façon dont vous le regardez. il est très possible qu'une simple fonction soit plus efficace. – Evgeny

3

La solution se révèle être très, très trivial: que la vitesse n'est pas une question super importante ici, appelant

Jobs.objects.update() 

avant que la requête ne l'affaire. Bravo à this post, qui détaille également quelques alternatives.

+0

bien, je ne savais pas que vous pouvez utiliser la mise à jour à cet effet. Est-ce que django frappe la base de données lors de l'appel à update()? – Evgeny

+0

en fait, vous pouvez également regarder dans la création d'un gestionnaire de modèle personnalisé, alors vous pouvez avoir Jobs.objects.claim_one() – Evgeny

Questions connexes