Building a powerful comment system
In this post, I am going to briefly descibe the challenges we faced while building a powerful comment system.
Comments have become an integral part of our website. They are integrated almost everywhere - challenges, problems, notes etc. and soon will be added to our new products. We have been working to make it more powerful and usable.
Here is what we did:
From the beginning
Our comment system is built using an open source django app, named django-threadedcomments. In threadedcomments, commenters can reply both to the original item, and reply to other comments as well. This open source app best suited our requirements in terms of UX, hence we decided to use it. But later we realised it was not powerful enough, and we decided to add our own features in it.
Pluggable architecture
Our commmenting system is a plug and play app. We added a layer on top of django-threadedcommnets which lets us integrate comments anywhere on our website easily without writing the same code again.
Below is the snippet which we can include in any django template to add comments.
<div id="comments-{{model.get_content_type.id}}-{{model.id}}" class="pagelet-inview standard-margin comments" ajax="{% url render_comments model.id model.get_content_type.id %}" target="comments-{{model.get_content_type.id}}-{{model.id}}"></div>
Above single line of code renders complete comment list(including reply form) using bigpipe. Isn’t it cool?
One more reason I am calling our comment system plug and play is that we can easily override most of the comments display logic, show comments differently on different pages. For example, comments appearing on a note and problem page needs to be shown differently based on the logic ‘who is the moderator of the content’. This couldn’t have been possible without django template block tag.
comments/base/list.html
comments/problem/list.html
comments/notes/list.html
Ajaxifying comments
This was the most challenging task because of the way django-threadedcomments is built. Special thanks to Virendra for taking the initiative and finding an easy to implement solution.
Posting a comment via AJAX request was realtively easy compared to deleting it because of comment’s threaded nature. Whenever a comment is deleted, we first determine if that comment has atleast a single child which is not deleted. Based on that logic we decide the format in which deleted comment will be shown to user. If you didn’t understand a word of what I wrote above, look at the images below.
Initial comments
After deleting comment 2, child comment 2.1 should be visible
After deleting comment 2.1, delete complete tree
We implemented BFS algorithm to handle all the scenarios and corner cases.
Realtime sync
After ajaxifying comments, we decide to put the cherry on top. Making comments appear in realtime was not easy at all. We are experimenting with Pusher to do the realtime job for us.
Below is generic python code for pushing data to pusher via rabbitmq:
Pusher is great for broadcasting messages in realtime but it has some drawbacks. It doesn’t have a scalable presence system, means it’s difficult to store more than 100 clients info on their servers. Thus making it difficult to write complex logic on client side.
Javascript code to post/delete comment
Tagging people
It does exactly what it says, that means you can now tag people in comments and they will be notified by email. Checkout the screenshot below.
Tagging people using @
Comment posted after tagging
I worked on this feature in our very first internal hackathon. I tried to make it as generic as possible by binding event handler on ‘mentionable’ class.
In backend we are querying from graph search database.
More to come
There are still a lot of improvements like UI changes etc. in pipeline which will be executed soon. If you have some suggestions, do let us know.
Hope these improvements have made comments on HackerEarth better and easier to engage.
Posted by Lalit Khattar. Follow me @LalitKhattar