Beispiel #1
0
    def add_comments(cls, link, comments):
        with cls._mutation_context(link) as lock:
            # adding comments requires read-modify-write, so get the lock
            tree = cls._load_tree(link)
            cids, _, _ = get_tree_details(tree)

            # skip any comments that are already in the stored tree and convert
            # to a set to remove any duplicate comments
            comments = {
                comment for comment in comments
                if comment._id not in cids
            }

            if not comments:
                return

            # warn on any comments whose parents are missing from the tree
            # because they will never be displayed unless their parent is
            # added. this can happen in normal operation if there are multiple
            # queue consumers and a child is processed before its parent.
            parent_ids = set(cids) | {comment._id for comment in comments}
            possible_orphan_comments = {
                comment for comment in comments
                if (comment.parent_id and comment.parent_id not in parent_ids)
            }
            if possible_orphan_comments:
                g.log.error("comment_tree_inconsistent: %s %s", link,
                    possible_orphan_comments)
                g.stats.simple_event('comment_tree_inconsistent')

            for comment in comments:
                tree.setdefault(comment.parent_id, []).append(comment._id)

            cls._write_tree(link, tree, lock)
Beispiel #2
0
    def by_link(cls, link, timer):
        key = cls._comments_key(link._id)
        r = g.permacache.get(key)
        timer.intermediate('load')

        if not r:
            # this link has not had an empty tree written for it. make an empty
            # tree here and return it. the downside is that until a comment is
            # added every time the storage for this link is requested it will
            # have a cache miss and fall through to cassandra
            return dict(cids=[], tree={}, depth={}, parents={})

        if isinstance(r, dict):
            tree = r
        else:
            try:
                # We got the old version that includes cids and depth
                _, tree, _ = r
            except ValueError:
                # We got the even older version that includes num_children
                _, tree, _, _ = r

        cids, depth, parents = get_tree_details(tree)
        timer.intermediate('calculate')

        return dict(cids=cids, tree=tree, depth=depth, parents=parents)
Beispiel #3
0
    def get_tree_pieces(cls, link, timer):
        key = cls._comments_key(link._id)
        tree = g.permacache.get(key)
        timer.intermediate('load')

        tree = tree or {}   # assume empty tree on miss
        cids, depth, parents = get_tree_details(tree)
        timer.intermediate('calculate')

        return cids, tree, depth, parents
Beispiel #4
0
    def get_tree_pieces(cls, link, timer):
        tree = cls._load_tree(link)
        timer.intermediate('load')

        cids, depth, parents = get_tree_details(tree)
        num_children = calc_num_children(tree)
        num_children = defaultdict(int, num_children)
        timer.intermediate('calculate')

        return cids, tree, depth, parents, num_children
def make_comment_tree(link):
    tree = {}

    def _add_comment(comment, parent):
        tree[comment.id] = [child.id for child in comment.children]
        for child in comment.children:
            _add_comment(child, parent=comment)

    tree[None] = [comment.id for comment in TREE]

    for comment in TREE:
        _add_comment(comment, parent=None)

    cids, depth, parents = get_tree_details(tree)
    num_children = calc_num_children(tree)
    num_children = defaultdict(int, num_children)

    return CommentTree(link, cids, tree, depth, parents, num_children)