Esempio n. 1
0
    def test_get_user_newsfeeds(self):
        newsfeed_timestamps = []
        for i in range(3):
            tweet = self.create_tweet(self.dongxie)
            newsfeed = self.create_newsfeed(self.linghu, tweet)
            newsfeed_timestamps.append(newsfeed.created_at)
        newsfeed_timestamps = newsfeed_timestamps[::-1]

        # cache miss
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual([f.created_at for f in newsfeeds],
                         newsfeed_timestamps)

        # cache hit
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual([f.created_at for f in newsfeeds],
                         newsfeed_timestamps)

        # cache updated
        tweet = self.create_tweet(self.linghu)
        new_newsfeed = self.create_newsfeed(self.linghu, tweet)
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        newsfeed_timestamps.insert(0, new_newsfeed.created_at)
        self.assertEqual([f.created_at for f in newsfeeds],
                         newsfeed_timestamps)
Esempio n. 2
0
def push_newsfeed_to_cache(sender, instance, created, **kwargs):
    # 只有新建时才push, update时并不push
    if not created:
        return

    from newsfeeds.services import NewsFeedService
    NewsFeedService.push_newsfeed_to_cache(instance)
Esempio n. 3
0
    def test_get_user_newsfeeds(self):
        newsfeed_ids = []
        for i in range(3):
            tweet = self.create_tweet(self.dongxie)
            newsfeed = self.create_newsfeed(self.linghu, tweet)
            newsfeed_ids.append(newsfeed.id)
        newsfeed_ids = newsfeed_ids[::-1]

        RedisClient.clear()
        conn = RedisClient.get_connection()

        # cache miss
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual([f.id for f in newsfeeds], newsfeed_ids)

        # cache hit
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual([f.id for f in newsfeeds], newsfeed_ids)

        # cache updated
        tweet = self.create_tweet(self.linghu)
        new_newsfeed = self.create_newsfeed(self.linghu, tweet)
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        newsfeed_ids.insert(0, new_newsfeed.id)
        self.assertEqual([f.id for f in newsfeeds], newsfeed_ids)
Esempio n. 4
0
    def follow(self, request, pk):

        #check if follow user exists
        self.get_object()
        if Friendship.objects.filter(from_user=request.user,to_user=pk):
            return Response({
                "success": True,
                "duplicate": True,
            }, HTTP_201_CREATED)
        if not User.objects.filter(id=pk).exists():
            logging.error(pk)
            logging.error(User.objects.filter(id=pk).exists())
            return Response({
                "success": False,
            }, HTTP_400_BAD_REQUEST)

        serializer = FriendshipSerializerForCreate(data={
            'from_user_id': request.user.id,
            'to_user_id': pk,
        })
        if not serializer.is_valid():
            return Response({
                "success": False,
                "message": "Invalid inputs.",
                "error": serializer.errors,
            }, HTTP_400_BAD_REQUEST)
        friendship = serializer.save()
        #populate newsfeed timeline for new friendship
        NewsFeedService.populate_newsfeed_for_friendship(friendship)
        return Response(
            FriendshipSerializerForCreate(friendship).data,
            status=HTTP_201_CREATED
        )
Esempio n. 5
0
    def test_fanout_main_task(self):
        tweet = self.create_tweet(self.ray, 'tweet 1')
        self.create_friendship(self.lux, self.ray)
        msg = fanout_newsfeeds_main_task(tweet.id, self.ray.id)
        self.assertEqual(
            msg, '1 newsfeeds are going to fanout, 1 batches created.')
        self.assertEqual(1 + 1, NewsFeed.objects.count())
        cached_list = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual(len(cached_list), 1)

        for i in range(2):
            user = self.create_user('user{}'.format(i))
            self.create_friendship(user, self.ray)
        tweet = self.create_tweet(self.ray, 'tweet 2')
        msg = fanout_newsfeeds_main_task(tweet.id, self.ray.id)
        self.assertEqual(
            msg, '3 newsfeeds are going to fanout, 1 batches created.')
        self.assertEqual(4 + 2, NewsFeed.objects.count())
        cached_list = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual(len(cached_list), 2)

        user = self.create_user('another user')
        self.create_friendship(user, self.ray)
        tweet = self.create_tweet(self.ray, 'tweet 3')
        msg = fanout_newsfeeds_main_task(tweet.id, self.ray.id)
        self.assertEqual(
            msg, '4 newsfeeds are going to fanout, 2 batches created.')
        self.assertEqual(8 + 3, NewsFeed.objects.count())
        cached_list = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual(len(cached_list), 3)
        cached_list = NewsFeedService.get_cached_newsfeeds(self.lux.id)
        self.assertEqual(len(cached_list), 3)
Esempio n. 6
0
    def test_fanout_main_task(self):
        tweet = self.create_tweet(self.linghu, 'tweet 1')
        self.create_friendship(self.dongxie, self.linghu)
        if GateKeeper.is_switch_on('switch_newsfeed_to_hbase'):
            msg = fanout_newsfeeds_main_task(tweet.id, tweet.timestamp,
                                             self.linghu.id)
            self.assertEqual(1 + 1,
                             len(HBaseNewsFeed.filter(prefix=(None, None))))
        else:
            msg = fanout_newsfeeds_main_task(tweet.id, tweet.created_at,
                                             self.linghu.id)
            self.assertEqual(1 + 1, NewsFeed.objects.count())

        self.assertEqual(msg,
                         '1 newsfeeds going to fanout, 1 batches created.')
        cached_list = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual(len(cached_list), 1)

        for i in range(2):
            user = self.create_user('user{}'.format(i))
            self.create_friendship(user, self.linghu)
        tweet = self.create_tweet(self.linghu, 'tweet 2')
        if GateKeeper.is_switch_on('switch_newsfeed_to_hbase'):
            msg = fanout_newsfeeds_main_task(tweet.id, tweet.timestamp,
                                             self.linghu.id)
            self.assertEqual(4 + 2,
                             len(HBaseNewsFeed.filter(prefix=(None, None))))
        else:
            msg = fanout_newsfeeds_main_task(tweet.id, tweet.created_at,
                                             self.linghu.id)
            self.assertEqual(4 + 2, NewsFeed.objects.count())
        self.assertEqual(msg,
                         '3 newsfeeds going to fanout, 1 batches created.')
        cached_list = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual(len(cached_list), 2)

        user = self.create_user('another user')
        self.create_friendship(user, self.linghu)
        tweet = self.create_tweet(self.linghu, 'tweet 3')
        if GateKeeper.is_switch_on('switch_newsfeed_to_hbase'):
            msg = fanout_newsfeeds_main_task(tweet.id, tweet.timestamp,
                                             self.linghu.id)
            self.assertEqual(8 + 3,
                             len(HBaseNewsFeed.filter(prefix=(None, None))))
        else:
            msg = fanout_newsfeeds_main_task(tweet.id, tweet.created_at,
                                             self.linghu.id)
            self.assertEqual(8 + 3, NewsFeed.objects.count())
        self.assertEqual(msg,
                         '4 newsfeeds going to fanout, 2 batches created.')
        cached_list = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual(len(cached_list), 3)
        cached_list = NewsFeedService.get_cached_newsfeeds(self.dongxie.id)
        self.assertEqual(len(cached_list), 3)
def fanout_newsfeeds_batch_task(tweet_id, follower_ids):
    from newsfeeds.services import NewsFeedService

    newsfeeds = [
        NewsFeed(user_id=follower_id, tweet_id=tweet_id)
        for follower_id in follower_ids
    ]
    NewsFeed.objects.bulk_create(newsfeeds)
    for newsfeed in newsfeeds:
        NewsFeedService.push_newsfeed_to_cache(newsfeed)

    return "{} newsfeeds created".format(len(newsfeeds))
Esempio n. 8
0
    def test_fanout_main_task(self):
        tweet1 = self.create_tweet(user=self.user1)
        self.create_friendship(from_user=self.user2, to_user=self.user1)
        msg = fanout_to_followers_main_task(tweet_id=tweet1.id,
                                            tweet_user_id=self.user1.id)
        self.assertEqual(msg,
            "1 newsfeeds are going to be fanout, " \
            "1 batches created, " \
            "batch size 3"
        )
        self.assertEqual(1 + 1, NewsFeed.objects.count())
        cached_list = NewsFeedService.load_newsfeeds_through_cache(
            user_id=self.user2.id)
        self.assertEqual(1, len(cached_list))

        # multiple users fanout
        for i in range(10):
            user = self.create_user(username='******'.format(i))
            self.create_friendship(from_user=user, to_user=self.user1)
        tweet2 = self.create_tweet(user=self.user1)
        msg = fanout_to_followers_main_task(
            tweet_id=tweet2.id,
            tweet_user_id=self.user1.id,
        )
        self.assertEqual(msg,
            "11 newsfeeds are going to be fanout, " \
            "4 batches created, " \
            "batch size 3"
        )
        self.assertEqual(2 + 12, NewsFeed.objects.count())
        cached_list = NewsFeedService.load_newsfeeds_through_cache(
            user_id=self.user2.id)
        self.assertEqual(2, len(cached_list))

        # cache invalidation
        self.clear_cache()
        user = self.create_user(username='******')
        self.create_friendship(from_user=user, to_user=self.user1)
        tweet3 = self.create_tweet(user=self.user1)
        msg = fanout_to_followers_main_task(
            tweet_id=tweet3.id,
            tweet_user_id=self.user1.id,
        )
        self.assertEqual(
            msg,
            "12 newsfeeds are going to be fanout, " \
            "4 batches created, " \
            "batch size 3"
        )
        self.assertEqual(3 + 24, NewsFeed.objects.count())
        cached_list = NewsFeedService.load_newsfeeds_through_cache(
            user_id=self.user2.id)
        self.assertEqual(3, len(cached_list))
Esempio n. 9
0
def fanout_newsfeeds_batch_task(tweet_id, follower_ids):
    from newsfeeds.services import NewsFeedService
    newsfeeds = [
        NewsFeed(user_id=follower_id, tweet_id=tweet_id)
        for follower_id in follower_ids
        # notice here the tweet.user is the creator of tweet
    ]
    NewsFeed.objects.bulk_create(newsfeeds)

    # bulk create will not invoke post_save signal, manually push newsfeed into cache
    for newsfeed in newsfeeds:
        NewsFeedService.push_newsfeed_to_cache(newsfeed)
    return "{} newsfeeds created".format(len(newsfeeds))
Esempio n. 10
0
 def create(self, request):
     serializer = TweetCreateSerializer(data=request.data,
                                        context={'request': request})
     if not serializer.is_valid():
         return Response(
             {
                 'success': False,
                 'message': 'Please check input',
                 'errors': serializer.errors,
             },
             status=400)
     tweet = serializer.save()
     NewsFeedService.fanout_to_followers(tweet)
     return Response(TweetSerializer(tweet).data, status=201)
Esempio n. 11
0
 def create(self, request):
     serializer = TweetSerializerForCreate(
         data=request.data,
         context={'request': request},
     )
     if not serializer.is_valid():
         return Response({
             "success": False,
             "message": "Please check input.",
             "errors": serializer.errors,
         }, status=400)
     # save will call create method in TweetSerializerForCreate
     tweet = serializer.save()
     NewsFeedService.fanout_to_followers(tweet)
     return Response(TweetSerializer(tweet).data, status=201)
Esempio n. 12
0
 def create_newsfeed(self, user, tweet):
     if GateKeeper.is_switch_on('switch_newsfeed_to_hbase'):
         created_at = tweet.timestamp
     else:
         created_at = tweet.created_at
     return NewsFeedService.create(user_id=user.id,
                                   tweet_id=tweet.id,
                                   created_at=created_at)
Esempio n. 13
0
    def test_redis_list_limit(self):
        list_limit = settings.REDIS_LIST_LENGTH_LIMIT
        page_size = 20
        users = [self.create_user('user{}'.format(i)) for i in range(5)]
        newsfeeds = []
        for i in range(list_limit + page_size):
            tweet = self.create_tweet(user=users[i % 5],
                                      content='feed{}'.format(i))
            feed = self.create_newsfeed(self.linghu, tweet)
            newsfeeds.append(feed)
        newsfeeds = newsfeeds[::-1]

        # only cached list_limit objects
        cached_newsfeeds = NewsFeedService.get_cached_newsfeeds(self.linghu.id)
        self.assertEqual(len(cached_newsfeeds), list_limit)

        if GateKeeper.is_switch_on('switch_newsfeed_to_hbase'):
            count = len(HBaseNewsFeed.filter(prefix=(self.linghu.id, None)))
        else:
            count = NewsFeed.objects.filter(user=self.linghu).count()
        self.assertEqual(count, list_limit + page_size)

        results = self._paginate_to_get_newsfeeds(self.linghu_client)
        self.assertEqual(len(results), list_limit + page_size)
        for i in range(list_limit + page_size):
            self.assertEqual(newsfeeds[i].created_at, results[i]['created_at'])

        # a followed user create a new tweet
        self.create_friendship(self.linghu, self.dongxie)
        new_tweet = self.create_tweet(self.dongxie, 'a new tweet')
        NewsFeedService.fanout_to_followers(new_tweet)

        def _test_newsfeeds_after_new_feed_pushed():
            results = self._paginate_to_get_newsfeeds(self.linghu_client)
            self.assertEqual(len(results), list_limit + page_size + 1)
            self.assertEqual(results[0]['tweet']['id'], new_tweet.id)
            for i in range(list_limit + page_size):
                self.assertEqual(newsfeeds[i].created_at,
                                 results[i + 1]['created_at'])

        _test_newsfeeds_after_new_feed_pushed()

        # cache expired
        self.clear_cache()
        _test_newsfeeds_after_new_feed_pushed()
Esempio n. 14
0
    def unfollow(self, request, pk):

        unfollow_user = self.get_object()
        if request.user.id == unfollow_user.id:
            return Response({
                "success": False,
                "message": "You cannot unfollow yourself."
            }, status=HTTP_400_BAD_REQUEST)
        friendship = Friendship.objects.filter(from_user=request.user,to_user_id=pk)
        #update timeline for the deleted following
        if friendship:
            NewsFeedService.update_newsfeed_for_unfollow(friendship[0])
        deleted, _ = friendship.delete()

        return Response({
            "success": True,
            "deleted": deleted
        }, status=HTTP_200_OK)
Esempio n. 15
0
def fanout_newsfeeds_batch_task(tweet_id, created_at, follower_ids):
    # import 写在里面避免循环依赖
    from newsfeeds.services import NewsFeedService
    batch_params = [
        {'user_id': follower_id, 'created_at': created_at, 'tweet_id': tweet_id}
        for follower_id in follower_ids
    ]
    newsfeeds = NewsFeedService.batch_create(batch_params)
    return "{} newsfeeds created".format(len(newsfeeds))
Esempio n. 16
0
    def create(self, request, *args, **kwargs):
        serializer = TweetSerializerForCreate(
            data=request.data,
            context={'request': request},
        )

        if not serializer.is_valid():
            return Response(
                {
                    'success': False,
                    'message': "please check input",
                    'errors': serializer.errors,
                },
                status=400)
        tweet = serializer.save()
        NewsFeedService.fanout_to_followers(tweet)
        serializer = TweetSerializer(tweet, context={'request': request})
        return Response(serializer.data, status=201)
Esempio n. 17
0
def fanout_newsfeeds_batch_task(tweet_id, follower_ids):
    # import 写在里面避免循环依赖
    from newsfeeds.services import NewsFeedService

    # 错误的方法:将数据库操作放在 for 循环里面,效率会非常低 ->
    # for follower_id in follower_ids:
    #     NewsFeed.objects.create(user_id=follower_id, tweet_id=tweet_id)
    # 正确的方法:使用 bulk_create,会把 insert 语句合成一条 ->
    newsfeeds = [
        NewsFeed(user_id=follower_id, tweet_id=tweet_id)
        for follower_id in follower_ids
    ]
    NewsFeed.objects.bulk_create(newsfeeds)
    # bulk create 不会触发 post_save 的 signal,所以需要手动 push 到 cache 里
    for newsfeed in newsfeeds:
        NewsFeedService.push_newsfeed_to_cache(newsfeed)

    return "{} newsfeeds created".format(len(newsfeeds))
Esempio n. 18
0
    def create(self, request):
        serialzier = TweetSerializerForCreate(
            data=request.data,
            context={'request': request},
        )

        if not serialzier.is_valid():
            return Response(
                {
                    "success": False,
                    "message": "Please check input.",
                    "errors": serialzier.errors,
                },
                status=HTTP_400_BAD_REQUEST)

        tweet = serialzier.save()
        #fan out to followers
        NewsFeedService.fan_out_to_followers(tweet)
        return Response(TweetSerializer(tweet).data, status=HTTP_201_CREATED)
Esempio n. 19
0
 def create(self, request):
     """
     重载 create 方法,因为需要默认用当前登录用户作为 tweet.user
     """
     serializer = TweetSerializerForCreate(
         data=request.data,
         context={'request': request},
     )
     if not serializer.is_valid():
         return Response({
             'success': False,
             'message': "Please check input",
             'errors': serializer.errors,
         }, status=400)
     # save() will call create method in TweetCreateSerializer
     tweet = serializer.save()
     NewsFeedService.fanout_to_followers(tweet)
     serializer = TweetSerializer(tweet, context={'request': request})
     return Response(serializer.data, status=201)
Esempio n. 20
0
 def create_newsfeed(self, user, tweet):
     # 默认ORM created_at:  2021-11-11 11:11:11.123456 iso format
     # HBaseModel: timestamp format: 16位int
     # 兼容 iso 格式和 int 格式的时间戳
     if GateKeeper.is_switch_on('switch_newsfeed_to_hbase'):
         created_at = tweet.timestamp
     else:
         created_at = tweet.created_at
     return NewsFeedService.create(user_id=user.id,
                                   tweet_id=tweet.id,
                                   created_at=created_at)
Esempio n. 21
0
def fanout_newsfeeds_batch_task(tweet_id, created_at, follower_ids):
    # we put import inside to avoid circular dependency
    from newsfeeds.services import NewsFeedService

    batch_params = [
        {'user_id': follower_id, 'created_at': created_at, 'tweet_id': tweet_id}
        for follower_id in follower_ids
    ]
    newsfeeds = NewsFeedService.batch_create(batch_params)

    return "{} newsfeeds created".format(len(newsfeeds))
Esempio n. 22
0
 def create(self, request, *args, **kwargs):
     """
     重载 create 方法,因为需要默认用当前登录用户作为 tweet.user
     """
     serializer = TweetCreateSerializer(
         data=request.data,
         context={'request': request},
     )
     # use default validator, like min max length
     if not serializer.is_valid():
         return Response(
             {
                 'success': False,
                 'message': "Please check input",
                 'errors': serializer.errors,
             },
             status=400)
     tweet = serializer.save()
     NewsFeedService.fanout_to_followers(tweet)
     return Response(TweetSerializer(tweet).data, status=201)
Esempio n. 23
0
 def list(self, request):
     cached_newsfeeds = NewsFeedService.get_cached_newsfeeds(request.user.id)
     page = self.paginator.paginate_cached_list(cached_newsfeeds, request)
     if page is None:
         queryset = NewsFeed.objects.filter(user=request.user)
         page = self.paginate_queryset(queryset)
     serializer = NewsFeedSerializer(
         page,
         context={'request': request},
         many=True,
     )
     return self.get_paginated_response(serializer.data)
Esempio n. 24
0
    def test_get_user_newsfeeds(self):
        newsfeed_ids = []
        for i in range(5):
            tweet = self.create_tweet(self.user2)
            newsfeed = self.create_newsfeed(self.user1, tweet)
            newsfeed_ids.append(newsfeed.id)
        newsfeed_ids = newsfeed_ids[::-1]

        #cache miss
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.user1.id)
        self.assertEqual([nf.id for nf in newsfeeds], newsfeed_ids)

        #cache hit
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.user1.id)
        self.assertEqual([nf.id for nf in newsfeeds], newsfeed_ids)

        tweet = self.create_tweet(self.user1)
        new_newsfeed = self.create_newsfeed(self.user1, tweet)
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.user1)
        newsfeed_ids.insert(0, new_newsfeed.id)
        self.assertEqual([nf.id for nf in newsfeeds], newsfeed_ids)
Esempio n. 25
0
    def create(self, request, *args, **kwargs):
        """
        overload create function, to default the login user as a tweet.user
        """
        serializer = TweetSerializerForCreate(
            data=request.data,
            context={'request': request},
        )

        if not serializer.is_valid():
            return Response(
                {
                    'success': False,
                    'message': 'Please check input',
                    'errors': serializer.errors,
                },
                status=400)
        tweet = serializer.save()
        NewsFeedService.fanout_to_followers(tweet)
        serializer = TweetSerializer(tweet, context={'request': request})
        return Response(serializer.data, status=201)
Esempio n. 26
0
 def create(self, request):
     serializer = TweetSerializerForCreate(
         data=request.data,
         context={'request': request},
     )
     if not serializer.is_valid():
         return Response({
             "success": False,
             "message": "Please check input",
             "errors": serializer.errors,
         }, status=400)
     # otherwise we have a tweet instance here
     # save() will call create method in TweetSerializerForCreate
     tweet = serializer.save()
     NewsFeedService.fanout_to_followers(tweet)
     # Here I use TweetSerializer to show whats in the tweet
     # reminder: It is different from TweetSerializerForCreate
     return Response(
         TweetSerializer(tweet, context={'request': request}).data,
         status=201,
     )
    def test_redis_list_limit(self):
        list_limit = settings.REDIS_LIST_LENGTH_LIMIT
        page_size = 20
        users = [self.create_user('user{}'.format(i)) for i in range(5)]
        newsfeeds = []
        for i in range(list_limit + page_size):
            tweet = self.create_tweet(user=users[i % 5],
                                      content='feed{}'.format(i))
            feed = self.create_newsfeed(self.ray, tweet)
            newsfeeds.append(feed)
        newsfeeds = newsfeeds[::-1]

        # only cached list_limit objects
        cached_newsfeeds = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual(len(cached_newsfeeds), list_limit)
        queryset = NewsFeed.objects.filter(user=self.ray)
        self.assertEqual(queryset.count(), list_limit + page_size)

        results = self._paginate_to_get_newsfeeds(self.ray_client)
        self.assertEqual(len(results), list_limit + page_size)
        for i in range(list_limit + page_size):
            self.assertEqual(newsfeeds[i].id, results[i]['id'])

        # a followed user create a new tweet
        self.create_friendship(self.ray, self.diana)
        new_tweet = self.create_tweet(self.diana, 'a new tweet')
        NewsFeedService.fanout_to_followers(new_tweet)

        def _test_newsfeeds_after_new_feed_pushed():
            results = self._paginate_to_get_newsfeeds(self.ray_client)
            self.assertEqual(len(results), list_limit + page_size + 1)
            self.assertEqual(results[0]['tweet']['id'], new_tweet.id)
            for i in range(list_limit + page_size):
                self.assertEqual(newsfeeds[i].id, results[i + 1]['id'])

        _test_newsfeeds_after_new_feed_pushed()

        # cache expired
        self.clear_cache()
        _test_newsfeeds_after_new_feed_pushed()
Esempio n. 28
0
    def test_get_user_newsfeeds(self):
        newsfeed_ids = []
        for i in range(3):
            tweet = self.create_tweet(self.lux)
            newsfeed = self.create_newsfeed(self.ray, tweet)
            newsfeed_ids.append(newsfeed.id)
        newsfeed_ids = newsfeed_ids[::-1]

        # cache miss
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual([f.id for f in newsfeeds], newsfeed_ids)

        # cache hit
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual([f.id for f in newsfeeds], newsfeed_ids)

        # cache updated
        tweet = self.create_tweet(self.ray)
        new_newsfeed = self.create_newsfeed(self.ray, tweet)
        newsfeeds = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        newsfeed_ids.insert(0, new_newsfeed.id)
        self.assertEqual([f.id for f in newsfeeds], newsfeed_ids)
Esempio n. 29
0
def fanout_newsfeeds_batch_task(tweet_id, follower_ids):
    # import written inside of method to avoid reference loop.
    from newsfeeds.services import NewsFeedService

    # wrong way:
    # can not put db operation in for loop. efficiency is super low and slow
    # for follower in FriendshipService.get_followers(tweet.user):
    #   NewsFeed.objects.create(
    #       user=follower,
    #       tweet=tweet,
    #   )
    # correct way: use bulk_create, then insert once
    newsfeeds = [
        NewsFeed(user_id=follower_id, tweet_id=tweet_id)
        for follower_id in follower_ids
    ]
    NewsFeed.objects.bulk_create(newsfeeds)

    # bulk create doesn't emit post_save signal, so, need to push each newsfeed to cache manually
    for newsfeed in newsfeeds:
        NewsFeedService.push_newsfeed_to_cache(newsfeed)
    return '{} newsfeeds created'.format(len(newsfeeds))
Esempio n. 30
0
    def test_create_new_newsfeed_before_get_cached_newsfeeds(self):
        feed1 = self.create_newsfeed(self.ray, self.create_tweet(self.ray))

        RedisClient.clear()
        conn = RedisClient.get_connection()

        key = USER_NEWSFEEDS_PATTERN.format(user_id=self.ray.id)
        self.assertEqual(conn.exists(key), False)
        feed2 = self.create_newsfeed(self.ray, self.create_tweet(self.ray))
        self.assertEqual(conn.exists(key), True)

        feeds = NewsFeedService.get_cached_newsfeeds(self.ray.id)
        self.assertEqual([f.id for f in feeds], [feed2.id, feed1.id])