annotate accounts/stats.py @ 768:1b1a12abde3b

More bio tests. Change Celery to be eager during testing.
author Brian Neal <bgneal@gmail.com>
date Tue, 21 Jan 2014 19:42:09 -0600
parents ee87ea74d46b
children
rev   line source
bgneal@520 1 """
bgneal@520 2 This module performs user account related statistics.
bgneal@520 3
bgneal@520 4 """
bgneal@520 5 import logging
bgneal@520 6
bgneal@520 7 from django.db.models.signals import post_save
bgneal@520 8 from django.contrib.auth.models import User
bgneal@520 9
bgneal@520 10 from core.services import get_redis_connection
bgneal@520 11
bgneal@520 12
bgneal@520 13 # Redis key names
bgneal@520 14 USER_COUNT_KEY = "accounts:user_count"
bgneal@520 15 NEW_USERS_KEY = "accounts:new_users"
bgneal@520 16
bgneal@520 17
bgneal@520 18 logger = logging.getLogger(__name__)
bgneal@520 19
bgneal@520 20
bgneal@520 21 def on_user_save(sender, **kwargs):
bgneal@520 22 """
bgneal@520 23 This function is our signal handler for when a User object is saved.
bgneal@520 24
bgneal@520 25 """
bgneal@520 26 from accounts.tasks import user_stats_task
bgneal@520 27
bgneal@520 28 if kwargs['created']:
bgneal@520 29 user = kwargs['instance']
bgneal@520 30
bgneal@520 31 # kick off a task to update user stats
bgneal@520 32
bgneal@520 33 user_stats_task.delay(user.id)
bgneal@520 34
bgneal@520 35
bgneal@520 36 def update_user_stats(user_id):
bgneal@520 37 """
bgneal@520 38 This function is given a new user id and is responsible for updating various
bgneal@520 39 user account statistics.
bgneal@520 40
bgneal@520 41 """
bgneal@520 42 try:
bgneal@520 43 user = User.objects.get(pk=user_id)
bgneal@520 44 except User.DoesNotExist:
bgneal@520 45 logger.warning("update_user_stats: user id %d doesn't exist", user_id)
bgneal@520 46 return
bgneal@520 47
bgneal@520 48 redis = get_redis_connection()
bgneal@520 49
bgneal@520 50 # update the count of registered users
bgneal@520 51
bgneal@520 52 count = redis.incr(USER_COUNT_KEY)
bgneal@520 53 if count == 1:
bgneal@520 54 # it is likely redis got wiped out; update it now
bgneal@520 55 count = User.objects.all().count()
bgneal@520 56 redis.set(USER_COUNT_KEY, count)
bgneal@520 57
bgneal@520 58 # update the list of new users
bgneal@520 59
bgneal@520 60 pipeline = redis.pipeline()
bgneal@520 61 pipeline.lpush(NEW_USERS_KEY, user.username)
bgneal@520 62 pipeline.ltrim(NEW_USERS_KEY, 0, 9)
bgneal@520 63 pipeline.execute()
bgneal@520 64
bgneal@520 65
bgneal@520 66 def get_user_count(redis=None):
bgneal@520 67 """
bgneal@520 68 This function returns the current count of users.
bgneal@520 69
bgneal@520 70 """
bgneal@520 71 if redis is None:
bgneal@520 72 redis = get_redis_connection()
bgneal@520 73 return redis.get(USER_COUNT_KEY)
bgneal@520 74
bgneal@520 75
bgneal@520 76 def get_new_users(redis=None):
bgneal@520 77 """
bgneal@520 78 This function returns a list of new usernames.
bgneal@520 79
bgneal@520 80 """
bgneal@520 81 if redis is None:
bgneal@520 82 redis = get_redis_connection()
bgneal@520 83 return redis.lrange(NEW_USERS_KEY, 0, -1)
bgneal@520 84
bgneal@520 85
bgneal@520 86 def get_user_stats(redis=None):
bgneal@520 87 """
bgneal@520 88 This function returns a tuple of the user stats. Element 0 is the user count
bgneal@520 89 and element 1 is the list of new users.
bgneal@520 90
bgneal@520 91 """
bgneal@520 92 if redis is None:
bgneal@520 93 redis = get_redis_connection()
bgneal@520 94 return get_user_count(redis), get_new_users(redis)
bgneal@520 95
bgneal@520 96
bgneal@520 97 post_save.connect(on_user_save, sender=User, dispatch_uid='accounts.stats')