Example #1
0
    def get_friends_for_user(self, request):
        """
        Pull the FacebookUsers that a user is connected to,
        from facebook if necessary
        If `async` is True, this returns an async_result, rather than blocking
        """
        # If we have a pending async request, let it finish
        async_result = request.session.get('pull_friends_async', None)
        if async_result:
            # There was an async in session, or we just created one
            # Commit the transaction so we can pull new results
            flush_transaction()
            try:
                # Wait for results
                async_result.get(timeout=5)
            except TimeoutError:
                # Let the exception go and handle the error in js
                raise
            del request.session['pull_friends_async']

        return self.filter(friend_of__owner=request.user)
Example #2
0
def top_friends_fast(user, friend_tag_end_time):
    """
    Pulls all friends and all tags,
    combines them to get `top_friends_score`
    and saves `FacebookUser` and `FacebookFriend` models
    """
    unix_friend_tag_end_time = unix_date_from_datetime(friend_tag_end_time)
    fql_job = group([
        rt.subtask(kwargs={'task_cls': GetFriendsTask,   'user_id': user.id, }),
        rt.subtask(kwargs={'task_cls': TaggedWithMeTask, 'user_id': user.id, 'end_time': unix_friend_tag_end_time }),
    ])
    job_async = fql_job.apply_async()
    results = job_async.get()

    all_friends = results['get_friends']
    tagged_with_me = results['tagged_with_me']

    # Collapse the tags by user_id, discount by age
    tag_score_by_user_id = defaultdict(lambda: 0.0)
    for tag in tagged_with_me.fields:
        tag_age = datetime.date.today().year - tag['created'].year + 1.0
        tag_score_by_user_id[tag['subject']] += 1 / tag_age

    # Sort
    user_ids_in_order = sorted(tag_score_by_user_id.iteritems(), key=lambda x: x[1])

    # Reversing them means the index corresponds to top friends order
    top_friends_order_by_id = {}
    for top_friends_order, u in enumerate(user_ids_in_order):
        top_friends_order_by_id[u[0]] = top_friends_order + 1   # 0 is not a valid value

    facebook_users = []
    facebook_friends = []
    for friend in all_friends:
        facebook_users.append(
            FacebookUser(
                facebook_id       = friend['id'],
                name              = friend['name'],
                first_name        = friend['first_name'],
                pic_square        = friend['pic_square'],
            )
        )
        facebook_friends.append(
            FacebookFriend(
                owner             = user,
                facebook_user_id  = friend['id'],
                top_friends_order = top_friends_order_by_id.get(friend['id'], 0)
            )
        )

    # Use the "bulk" library rather than the built-in
    # `bulk_create` so we can specify ON DUPLICATE KEY UPDATE
    #  -- getter guarantees that all fields are filled
    bulk.insert_or_update_many(FacebookUser, facebook_users)
    flush_transaction()

    # Insert is faster, we don't care about preserving other fields
    bulk.insert_or_update_many(FacebookFriend, facebook_friends, keys=['owner', 'facebook_user'])
    flush_transaction()

    return results