Not that it matters, but this is a follow-up to this question.
开发者_C百科I want to keep a count of how many times each object in my database has been viewed. Let's say we have a Person
model, with several instances. We want to keep a counter of how many times each instance has been viewed in the Person
model, using Django Celery to avoid waiting for the database writes.
At the moment I'm doing this:
from celery.decorators import task
class Person(models.Model):
name = models.CharField(max_length=50)
class Stats(models.Model):
person = models.ForeignKey('Person', unique=True)
@task
def addView(self):
se = StatEvent()
se.save()
self.views.add(se)
class StatEvent(models.Model):
date = models.DateTimeField(auto_now_add=True)
Then, every time the view is called which lists a page of persons, I get all persons, update the statistics like this:
person.get_stats().addView.delay(person.get_stats())
where after I then return the list of persons to be displayed in the browser. I thought that the updating of the statistics would happen asynchronously, but there's a clear and long delay before the page is displayed, which is confirmed by having a print
statement shown for each addition in the Celery command window. The page is only rendered once the last statistic has been updated.
How do I ensure that the user doesn't wait for the database update to finish?
Update
I thought it might have something to do with there not being enough worker processes to process each person separately, so I instead made a function that accepts a list of persons as parameter, and used this as the task to be executed. So, only one task in the queue:
@task(ignore_result=True)
def addViews(persons):
for person in persons:
stats = listing.get_stats()
se = StatEvent()
se.save()
stats.views.add(se)
However, when print to the console, like this:
print "adding"
print tasks.addClicks(persons)
print "done"
Then there's a clear delay between the "adding" and "done" step, and the returned value of the function is None
.
Turns out my original suspicion about there not being enough workers was correct. My new function that put everything in one task solved the problem - I was just missing the .delay
in that last tasks.addClicks(persons)
call.
精彩评论