def delete_status(uid, status_id): key = 'status:%s' % status_id with Lock(key) as lock: if not lock: return False status = Status.load(status_id=status_id) if not status or status.user_id != uid: return False status_db = redis_mapping.get_db('status') pipeline = status_db.pipeline() data = status.to_json() data['deleted'] = True pipeline.publish('streaming:status:', json.dump(data)) pipeline.zrem('profile:%s' % uid, status_id) pipeline.zrem('home:%s' % uid, status_id) pipeline.execute() user_db = redis_mapping.get_db('session') user_db.hincrby('user:%s' % uid, 'posts', -1) Status.remove_one({'status_id': status_id}) return True
def follow_user(uid, other_uid): redis_db = redis_mapping.get_db('status') fkey1 = 'followings:%s' % uid fkey2 = 'followers:%s' % other_uid if redis_db.zscore(fkey1, other_uid): return False now = int(time.time()) pipeline = redis_db.pipeline() pipeline.zadd(fkey1, {other_uid: now}) pipeline.zadd(fkey2, {uid: now}) pipeline.zrevrange('profile:%s' % other_uid, 0, STATUS_HOME_TIMELINE_SIZE - 1, withscores=True) followings, followers, status_and_score = pipeline.execute()[-3:] if status_and_score: pipeline.zadd('home:%s' % uid, dict(status_and_score)) pipeline.zremrangebyrank('home:%s' % uid, 0, -STATUS_HOME_TIMELINE_SIZE - 1) pipeline.execute() user_db = redis_mapping.get_db('session') pipeline = user_db.pipeline() pipeline.hincrby('user:%s' % uid, 'followings', int(followings)) pipeline.hincrby('user:%s' % other_uid, 'followers', int(followers)) pipeline.execute() return True
def create_status(content, user_id): user = User.load(user_id=user_id) if not user: return None status_id = gen_status_id() now = datetime.now() status = Status() status.status_id = status_id status.content = content status.user_id = user_id status.nickname = user.nickname status.create_time = now status.publish_status = PublishStatus.INIT.value status.save_new() status_db = redis_mapping.get_db('status') status_db.publish('streaming:status:', json.dumps(status.to_json())) user_db = redis_mapping.get_db('session') user_db.hincrby('user:%s' % user_id, 'posts') # 处理 redis 记录 return status
def unfollow_user(uid, other_uid): redis_db = redis_mapping.get_db('status') fkey1 = 'followings:%s' % uid fkey2 = 'followers:%s' % other_uid if not redis_db.zscore(fkey1, other_uid): return False pipeline = redis_db.pipeline() pipeline.zrem(fkey1, other_uid) pipeline.zrem(fkey2, uid) pipeline.zrevrange('profile:%s' % other_uid, 0, STATUS_HOME_TIMELINE_SIZE - 1) followings, followers, status = pipeline.execute()[-3:] if status: pipeline.zrem('home:%s' % uid, *status) pipeline.execute() user_db = redis_mapping.get_db('session') pipeline = user_db.pipeline() pipeline.hincrby('user:%s' % uid, 'followings', -abs(followings)) pipeline.hincrby('user:%s' % other_uid, 'followers', -abs(followers)) pipeline.execute() return True
def create_user(username, pwd_md5, nickname): """创建新用户""" key = 'user:'******'session') user_db.hmset( 'user:%s' % user_id, { 'user_id': user_id, 'nickname': nickname, 'followers': 0, 'followings': 0, 'posts': 0, 'login': datetime.timestamp(now) }) return user
def filter_content(user_id, filter_type, arg, quit): """过滤内容,推荐内容""" redis_db = redis_mapping.get_db('status') match = create_filters(user_id, filter_type, arg) pubsub = redis_db.pubsub() pubsub.subscribe(['streaming:status:']) for item in pubsub.listen(): message = item['data'] decoded = json.loads(message) if match(decoded): if decoded.get('deleted'): yield json.dumps({ 'status_id': decoded['status_id'], 'deleted': True }) else: yield message if quit[0]: break pubsub.reset()
def syndicate_status(uid, status_id, timestamp, start=0): redis_db = redis_mapping.get_db('status') followers = redis_db.zrangebyscore('followers:%s' % uid, start, 'inf', start=0, num=POST_PER_PASS) pipeline = redis_db.pipeline() for follower in followers: pipeline.zadd('home:' + follower, {status_id: timestamp}) pipeline.zremrangebyrank('home:' + follower, 0, -STATUS_HOME_TIMELINE_SIZE - 1) pipeline.execute() # 自己的主页 pipeline.zadd('home:%s' % uid, {status_id: timestamp}) pipeline.zremrangebyrank('home:%s' % uid, 0, -STATUS_HOME_TIMELINE_SIZE - 1) pipeline.execute() # TODO 延迟同步 return True
def post_status(uid, content, **data): status = create_status(content, uid) if not status: return None now = datetime.timestamp(status.create_time) redis_db = redis_mapping.get_db('status') pipeline = redis_db.pipeline() pipeline.zadd('profile:%s' % uid, {status.status_id: now}) syndicate_status(uid, status.status_id, now) return True
def logout_user(token: str): """用户注销""" key = 'user:logout:' + token with Lock(key) as lock: if not lock: return False redis_db = redis_mapping.get_db('session') user_key = SESSION_USER_KEY.format(token=token) user_id = redis_db.get(user_key) if not user_id: return False token_key = SESSION_TOKEN_KEY.format(user_id=user_id) pipeline = redis_db.pipeline() pipeline.delete(user_key) pipeline.delete(token_key) pipeline.execute() return True
def login_user(user: User): """用户登录""" redis_db = redis_mapping.get_db('session') user.login_time = datetime.now() user.update() token = get_random_str() pipeline = redis_db.pipeline() user_key = SESSION_USER_KEY.format(token=token) pipeline.set(user_key, user.user_id, ex=config.SESSION_EXPIRE_TIME) token_key = SESSION_TOKEN_KEY.format(user_id=user.user_id) pipeline.set(token_key, token, ex=config.SESSION_EXPIRE_TIME) pipeline.zadd(SESSION_RECENT_ZKEY, {user.user_id: int(time.time())}) # 清理登录状态,可以单独起一个程序清理,否则每秒执行次数太多 pipeline.zremrangebyrank(SESSION_RECENT_ZKEY, 0, -1000) pipeline.execute() return token
def get_status_contents(user_id, timeline='home', page=1, count=30): """获取时间线的状态消息列表""" redis_db = redis_mapping.get_db('status') pipeline = redis_db.pipeline() pipeline.zrevrange('%s:%s' % (timeline, user_id), (page - 1) * count, page * count - 1) pipeline.zcount('%s:%s' % (timeline, user_id), 0, 'inf') statuses, total = pipeline.execute()[-2:] statuses = list(map(int, statuses)) query_dict = {'status_id': {'$in': statuses}} sort = ['-create_time'] items = [] for status in Status.query(query_dict, sort): items.append({ 'status_id': status['status_id'], 'content': status['content'], 'user_id': status['user_id'], 'create_time': status['create_time'] }) return {'total': total, 'items': items, 'page': page, 'count': count}
def __init__(self, key, timeout=10): self.db = redis_mapping.get_db('lock') self.timeout = timeout self.key = key self.lock = None
def gen_user_id(): """自增生成新的用户id""" redis_db = redis_mapping.get_db('counter') return int(redis_db.incr(USER_ID_COUNTER_KEY))
def check_token(token: str): """检查登录状态""" redis_db = redis_mapping.get_db('session') user_key = SESSION_USER_KEY.format(token=token) return int(redis_db.get(user_key) or 0)
# -*- coding: utf-8 -*- from datetime import datetime from utils.words import tokenize from utils.db import zunion, zintersect, union from utils.ip import ip_to_score from app import redis_mapping from app.models.ad import Ad redis_db = redis_mapping.get_db('ad') def gen_ad_id(): key = 'counter:ad_id' return str(redis_db.incr(key)) def get_ad(ad_id): ad = Ad.load(ad_id=ad_id) return ad def add_ad(name, locations, content, type, value): ad_id = gen_ad_id() ad = Ad() ad.ad_id = ad_id ad.name = name ad.type = type ad.content = content ad.locations = locations
def gen_status_id(): """自增生成新的用户id""" redis_db = redis_mapping.get_db('counter') return int(redis_db.incr(STATUS_ID_COUNTER_KEY))