diff gpp/accounts/stats.py @ 520:e94570675664

Created stats for users (number of users and list of newest users). Better separated the forums, who's online, and user stats. Use a Celery task to execute the new user stats processing. This addresses #194 and #238.
author Brian Neal <bgneal@gmail.com>
date Sat, 17 Dec 2011 23:19:15 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/accounts/stats.py	Sat Dec 17 23:19:15 2011 +0000
@@ -0,0 +1,97 @@
+"""
+This module performs user account related statistics.
+
+"""
+import logging
+
+from django.db.models.signals import post_save
+from django.contrib.auth.models import User
+
+from core.services import get_redis_connection
+
+
+# Redis key names
+USER_COUNT_KEY = "accounts:user_count"
+NEW_USERS_KEY = "accounts:new_users"
+
+
+logger = logging.getLogger(__name__)
+
+
+def on_user_save(sender, **kwargs):
+    """
+    This function is our signal handler for when a User object is saved.
+
+    """
+    from accounts.tasks import user_stats_task
+
+    if kwargs['created']:
+        user = kwargs['instance']
+
+        # kick off a task to update user stats
+
+        user_stats_task.delay(user.id)
+
+
+def update_user_stats(user_id):
+    """
+    This function is given a new user id and is responsible for updating various
+    user account statistics.
+
+    """
+    try:
+        user = User.objects.get(pk=user_id)
+    except User.DoesNotExist:
+        logger.warning("update_user_stats: user id %d doesn't exist", user_id)
+        return
+
+    redis = get_redis_connection()
+
+    # update the count of registered users
+
+    count = redis.incr(USER_COUNT_KEY)
+    if count == 1:
+        # it is likely redis got wiped out; update it now
+        count = User.objects.all().count()
+        redis.set(USER_COUNT_KEY, count)
+
+    # update the list of new users
+
+    pipeline = redis.pipeline()
+    pipeline.lpush(NEW_USERS_KEY, user.username)
+    pipeline.ltrim(NEW_USERS_KEY, 0, 9)
+    pipeline.execute()
+
+
+def get_user_count(redis=None):
+    """
+    This function returns the current count of users.
+
+    """
+    if redis is None:
+        redis = get_redis_connection()
+    return redis.get(USER_COUNT_KEY)
+
+
+def get_new_users(redis=None):
+    """
+    This function returns a list of new usernames.
+
+    """
+    if redis is None:
+        redis = get_redis_connection()
+    return redis.lrange(NEW_USERS_KEY, 0, -1)
+
+
+def get_user_stats(redis=None):
+    """
+    This function returns a tuple of the user stats. Element 0 is the user count
+    and element 1 is the list of new users.
+
+    """
+    if redis is None:
+        redis = get_redis_connection()
+    return get_user_count(redis), get_new_users(redis)
+
+
+post_save.connect(on_user_save, sender=User, dispatch_uid='accounts.stats')