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')
|