Ejemplo n.º 1
0
    def unfollow(cls, from_user_id, to_user_id):
        if from_user_id == to_user_id:
            return 0

        if not GateKeeper.is_switched_on('switch_friendship_to_hbase'):
            # https://docs.djangoproject.com/en/3.1/ref/models/querysets/#delete
            # Queryset 的 delete 操作返回两个值,一个是删了多少数据,一个是具体每种类型删了多少
            # 为什么会出现多种类型数据的删除?因为可能因为 foreign key 设置了 cascade 出现级联
            # 删除,也就是比如 A model 的某个属性是 B model 的 foreign key,并且设置了
            # on_delete=models.CASCADE, 那么当 B 的某个数据被删除的时候,A 中的关联也会被删除。
            # 所以 CASCADE 是很危险的,我们一般最好不要用,而是用 on_delete=models.SET_NULL
            # 取而代之,这样至少可以避免误删除操作带来的多米诺效应。
            deleted, _ = Friendship.objects.filter(
                from_user_id=from_user_id,
                to_user_id=to_user_id,
            ).delete()
            return deleted

        instance = cls.get_follow_instance(from_user_id, to_user_id)
        if instance is None:
            return 0

        HBaseFollowing.delete(from_user_id=from_user_id,
                              created_at=instance.created_at)
        HBaseFollower.delete(to_user_id=to_user_id,
                             created_at=instance.created_at)
        return 1
Ejemplo n.º 2
0
    def follow(cls, from_user_id, to_user_id):
        if from_user_id == to_user_id:
            return None

        if not GateKeeper.is_switched_on('switch_friendship_to_hbase'):
            # create data in mysql
            return Friendship.objects.create(
                from_user_id=from_user_id,
                to_user_id=to_user_id,
            )

        # create data in hbase
        # first we retrieve the current time and store it in a local variable
        # in case there are inconsistencies between the two records that we created in those two tables
        now = int(time.time() * 1000000)
        HBaseFollower.create(
            from_user_id=from_user_id,
            to_user_id=to_user_id,
            created_at=now,
        )
        return HBaseFollowing.create(
            from_user_id=from_user_id,
            to_user_id=to_user_id,
            created_at=now,
        )
Ejemplo n.º 3
0
    def follow(cls, from_user_id, to_user_id):
        if from_user_id == to_user_id:
            return None

        # update Redis
        cls.add_following_id_in_redis(from_user_id, to_user_id)

        # update DB
        if not GateKeeper.is_switch_on('switch_friendship_to_hbase'):
            # create data in MySQL
            return Friendship.objects.create(
                from_user_id=from_user_id,
                to_user_id=to_user_id,
            )

        # create data in hbase
        now = int(time.time() * 1000000)
        HBaseFollower.create(
            from_user_id=from_user_id,
            to_user_id=to_user_id,
            created_at=now,
        )
        return HBaseFollowing.create(
            from_user_id=from_user_id,
            to_user_id=to_user_id,
            created_at=now,
        )
Ejemplo n.º 4
0
    def get_following_user_id_set(cls, from_user_id):
        # cache set in Redis
        name = FOLLOWINGS_PATTERN.format(user_id=from_user_id)
        user_id_set = RedisHelper.get_all_members_from_set(name)

        # cache hit, need to change b'123' -> 123
        if user_id_set is not None:
            user_id_set_new = set([])
            for user_id in user_id_set:
                if isinstance(user_id, bytes):
                    user_id = user_id.decode('utf-8')
                    user_id_set_new.add(int(user_id))
            return user_id_set_new

        # cache miss
        if not GateKeeper.is_switch_on('switch_friendship_to_hbase'):
            friendships = Friendship.objects.filter(from_user_id=from_user_id)
        else:
            friendships = HBaseFollowing.filter(prefix=(from_user_id, None))
        user_id_set = set([
            fs.to_user_id
            for fs in friendships
        ])

        # push in Redis
        RedisHelper.add_id_to_set(name, user_id_set)
        return user_id_set
Ejemplo n.º 5
0
 def get_following_user_id_set(cls, from_user_id):
     # <todo> cache in redis set
     if not GateKeeper.is_switch_on('switch_friendship_to_hbase'):
         friendships = Friendship.objects.filter(from_user_id=from_user_id)
     else:
         friendships = HBaseFollowing.filter(prefix=(from_user_id, None))
     user_id_set = set([fs.to_user_id for fs in friendships])
     return user_id_set
Ejemplo n.º 6
0
 def get_following_user_id_set(cls, from_user_id):
     # <TODO> cache in redis set
     if not GateKeeper.is_switched_on('switch_friendship_to_hbase'):
         friendships = Friendship.objects.filter(from_user_id=from_user_id)
     else:
         friendships = HBaseFollowing.filter(prefix=(from_user_id, None))
     # we use a set to hold a data because it is fast to check whether an elements exists there
     user_id_set = set([fs.to_user_id for fs in friendships])
     return user_id_set
Ejemplo n.º 7
0
    def test_save_and_get(self):
        timestamp = self.ts_now
        following = HBaseFollowing(from_user_id=123, to_user_id=34, created_at=timestamp)
        following.save()

        instance = HBaseFollowing.get(from_user_id=123, created_at=timestamp)
        self.assertEqual(instance.from_user_id, 123)
        self.assertEqual(instance.to_user_id, 34)
        self.assertEqual(instance.created_at, timestamp)

        following.to_user_id = 456
        following.save()

        instance = HBaseFollowing.get(from_user_id=123, created_at=timestamp)
        self.assertEqual(instance.to_user_id, 456)

        #object does not exist, return None
        instance = HBaseFollowing.get(from_user_id=123, created_at=self.ts_now)
        self.assertEqual(instance, None)
Ejemplo n.º 8
0
    def unfollow(cls, from_user_id, to_user_id):
        if from_user_id == to_user_id:
            return 0

        # update Redis
        cls.remove_following_id_in_redis(from_user_id, to_user_id)

        # update DB
        if not GateKeeper.is_switch_on('switch_friendship_to_hbase'):
            deleted, _ = Friendship.objects.filter(
                from_user_id=from_user_id,
                to_user_id=to_user_id,
            ).delete()
            return deleted
        instance = cls.get_follow_instance(from_user_id, to_user_id)
        if instance is None:
            return 0

        HBaseFollowing.delete(from_user_id=from_user_id, created_at=instance.created_at)
        HBaseFollower.delete(to_user_id=to_user_id, created_at=instance.created_at)
        return 1
Ejemplo n.º 9
0
    def follow(cls, from_user_id, to_user_id):
        if from_user_id == to_user_id:
            return None

        if not GateKeeper.is_switch_on('switch_friendship_to_hbase'):
            # create data in mysql
            return Friendship.objects.create(
                from_user_id=from_user_id,
                to_user_id=to_user_id,
            )

        # create data in hbase
        now = int(time.time() * 1000000)
        HBaseFollower.create(
            from_user_id=from_user_id,
            to_user_id=to_user_id,
            created_at=now,
        )
        return HBaseFollowing.create(
            from_user_id=from_user_id,
            to_user_id=to_user_id,
            created_at=now,
        )
Ejemplo n.º 10
0
 def get_follow_instance(cls, from_user_id, to_user_id):
     followings = HBaseFollowing.filter(prefix=(from_user_id, None))
     for follow in followings:
         if follow.to_user_id == to_user_id:
             return follow
     return None
Ejemplo n.º 11
0
    def get_following_count(cls, from_user_id):
        if not GateKeeper.is_switched_on('switch_friendship_to_hbase'):
            return Friendship.objects.filter(from_user_id=from_user_id).count()

        followings = HBaseFollowing.filter(prefix=(from_user_id, None))
        return len(followings)
Ejemplo n.º 12
0
    def test_filter(self):
        HBaseFollowing.create(from_user_id=1,
                              to_user_id=2,
                              created_at=self.ts_now)
        HBaseFollowing.create(from_user_id=1,
                              to_user_id=3,
                              created_at=self.ts_now)
        HBaseFollowing.create(from_user_id=1,
                              to_user_id=4,
                              created_at=self.ts_now)

        followings = HBaseFollowing.filter(prefix=(1, ))
        self.assertEqual(3, len(followings))
        self.assertEqual(followings[0].from_user_id, 1)
        self.assertEqual(followings[0].to_user_id, 2)
        self.assertEqual(followings[1].from_user_id, 1)
        self.assertEqual(followings[1].to_user_id, 3)
        self.assertEqual(followings[2].from_user_id, 1)
        self.assertEqual(followings[2].to_user_id, 4)

        # test limit
        results = HBaseFollowing.filter(prefix=(1, ), limit=1)
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0].to_user_id, 2)

        results = HBaseFollowing.filter(prefix=(1, ), limit=2)
        self.assertEqual(len(results), 2)
        self.assertEqual(results[0].to_user_id, 2)
        self.assertEqual(results[1].to_user_id, 3)

        results = HBaseFollowing.filter(prefix=(1, ), limit=4)
        self.assertEqual(len(results), 3)
        self.assertEqual(results[0].to_user_id, 2)
        self.assertEqual(results[1].to_user_id, 3)
        self.assertEqual(results[2].to_user_id, 4)

        results = HBaseFollowing.filter(start=(1, results[1].created_at),
                                        limit=2)
        self.assertEqual(len(results), 2)
        self.assertEqual(results[0].to_user_id, 3)
        self.assertEqual(results[1].to_user_id, 4)

        # test reverse
        results = HBaseFollowing.filter(prefix=(1, ), limit=2, reverse=True)
        self.assertEqual(len(results), 2)
        self.assertEqual(results[0].to_user_id, 4)
        self.assertEqual(results[1].to_user_id, 3)

        results = HBaseFollowing.filter(start=(1, results[1].created_at),
                                        limit=2,
                                        reverse=True)
        self.assertEqual(len(results), 2)
        self.assertEqual(results[0].to_user_id, 3)
        self.assertEqual(results[1].to_user_id, 2)