ユーザの最終アクセス時刻をDBで記録していたけど、頻繁に更新したいけどDBだとボトルネックになるので、redisで置き換えたコード。
利点
- zscoreで記録することで、リアルタイムに誰がアクセスしたかが分かる(fluentとかでログはいても確認できるけど)。
- zrangebyscoreを使用すると、最終サクセス日が現在より24時間以内のユーザ一覧が出せる。
lastaccess.py
from datetime import datetime
import pytz
import redis
class UserLastAccess(object):
def __init__(self, user_id):
self._user_id = user_id
self._client = redis.StrictRedis()
self._key = self.__class__.__name__
@property
def accessed_at(self):
timestamp = self._client.zscore(self._key, self._user_id)
if timestamp:
d = datetime.fromtimestamp(int(timestamp))
return pytz.timezone('Asia/Tokyo').normalize(pytz.utc.localize(d))
return None
def touch(self):
now = pytz.utc.localize(datetime.utcnow())
timestamp = now.strftime('%s')
self._client.zadd(self._key, timestamp, self._user_id)
return pytz.timezone('Asia/Tokyo').normalize(now)
class LastAccessedAtMixin(object):
@property
def user_last_access(self):
return UserLastAccess(self.id)
@property
def last_accessed_at(self):
return self.user_last_access.accessed_at
def touch(self):
return self.user_last_access.touch()
class User(LastAccessedAtMixin):
def __init__(self, user_id):
self.id = user_id
使用例
ex
user = User('1000')
user.touch() # => datetime.datetime(2014, 10, 6, 21, 55, 27, 654918, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
user.last_accessed_at # => datetime.datetime(2014, 10, 6, 21, 55, 27, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)