Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Google Summer of Code 2021 Zulip work report

Google Summer of Code work report

This document is a summary of the work that I did as a student developer in the Zulip open source project, as part of Google Summer of Code 2021.

Quick links

GitHub profile: abhijeetbodas2001
Repository contributed to: zulip/zulip
Merged pull requests:


During the coding period, my work was mainly focused on improving Zulip's notifications system. The projects I worked on are listed below, along with the relevant pull requests.

Configurable grace period for email notifications

New feature implemented, which will allow users to set custom aggregation periods for email notifications (like "one hour" or "one week"), which basically means the user will receive all Zulip-message related emails once every set duration, instead of immediately after the message is sent.
Also fixed the email notifications queue worker to be robust towards server downtime by utilizing database storage (instead of in-memory Python maps).

#19576 Complete custom email notification batching period feature.
#19312 MissedMessageWorker: Handle deleted messages
#19229 worker: Ensure complete coverage for PushNotificationsWorker.
#19119 worker: Make MissedMessageWorker not be lossy.

User group mention notifications

Earlier, if a user group was mentioned (@user_group), the email and push notifications would not contain the user group's name, but instead made it look like the user was personally mentioned (@username). Fixed this to correctly show the name of the mentioned user group, and passed the user group ID in the push notifications payload to make it possible for the mobile app to further process it if required.

#19172 push_notifications: Send mentioned user group ID and name in payload.
#19170 notifications: Remove unused fields in notices.
#19085 Display which user group was mentioned in email/push notifications.

Event queue refactors

Refactoring projects done to make the event queue code more maintainable, and to make it easier to add new features. This involved extracting most of the notifiability-determining logic into a new dataclass in a new file (zerver/lib/ This also fixed various subtle bugs in the system as a side-effect.

#19246 notifications: Calculate PMs/mentions settings like other settings.
#19004 notification_data: Use acting_user_id as variable name, not sender_id.
#18969 refactor: Change maybe_enqueue_notifications to take in notifications dataclass instance.
#18951 Use UserMessageNotificationsData in process_message_update_event
#18853 Introduce new dataclass for message send event user data.
#18803 event_queue: Don't check for "read" flag when processing events.
#18742 Cleanup maybe_enqueue_notifs test to send only changed parameters.
#18725 actions and event_queue miscellaneous refactors.
#18719 Decouple muted-user notification blocking from read flag.
#18578 Rename some notifications related variables for clarity.
#18561 Pass individual parameters to build_message_send_dict instead of a single dictionary.

Fixing message deletion related race conditions

Fixing IntegrityErrors raised when a message reaction is added/removed concurrently with deleting the message. This was done by using SELECT FOR UPDATE queries and database transactions.

#19281 do_update_embedded_data: Remove unnecessary transaction.atomic.
#18559 Handle race conditions from deleting a message and adding/removing related fields simultaneously.

Test suite clean-ups

Work towards making the node test suite and backend test suite more consistent and clean.

#18830 Use mock_template in more node tests.
#18637 Further improve tornado_redirected_to_list
#18626 Cleanup send_event mocks.
#18522 Consistently use self.assert_length in tests.

Followed topics (Work in progress)

Worked on a new feature - "topics I follow", which will allow users to get notified if a message is sent within a certain topic. This is currently work in progress, and some of the preparatory work is done in the following pull requests:

#19430 Prep changes for follow topic
#19388 Rename MutedTopic to UserTopic


Minor bug fixes and commits, not related to any major project.

#19551 notifications: Fix unnecessary wildcard mention notifications.
#19350 ui_init: Fix "Error: Unknown user_id in get_by_user_id: 0".
#19081 docs: Split widgets and slash command developer pages.
#18606 Fix HTTP 500 when topic specified for private message edit.

Complete list of merged commits

A total of 219 commits authored by me were merged into zulip/zulip untill 15th August 2021. What follows is a list of links to those commits, along with short descriptions. The list was generated with the help of PyGithub.

Coding period (17 May 2021 to 23 August 2021, 111 commits)

ac70a2d notifications: Fix unnecessary wildcard mention notifications.
de04f0a notifications: Calculate PMs/mentions settings like other settings.
683c850 models: Remove MutedTopic alias for UserTopic.
798defc models: Rename MutedTopic to UserTopic.
5db4fe8 api: Allow setting email_notifications_batching_period_seconds.
dd5e12d MissedMessageWorker: Use custom batching periods from UserProfile.
d5d3f14 models: Add UserProfile field for custom email notifs batching periods.
9fcb6e5 MissedMessageWorker: Handle deleted messages.
de78b01 MissedMessageWorker: Remove unnecessary transaction.atomic.
d0b3801 ui_init: Fix "Error: Unknown user_id in get_by_user_id: 0".
2545f00 do_update_embedded_data: Remove unnecessary transaction.atomic.
9901b72 tests: Purge queue before starting tests, not at tearDown.
ebb4eab worker: Rewrite MissedMessageWorker to not be lossy.
1709428 models: Create MissedMessageEmailEntry table.
c3319a5 notification_data: Create common source for trigger strings.
e63e86d worker: Ensure complete coverage for PushNotificationsWorker.
bf15c02 notifications: Remove unused fields in queue events.
76dc504 push_notifications: Remove outdated comments.
4f9c7ca push_notifications: Send mentioned user group ID and name in payload.
9bd8fe0 android push notifications: Display mentioned user group name.
4d24499 android notifications: Differentiate personal vs wildcard mentions.
ce6f6a3 push_notifications: Pre-calculate mentioned_user_group_name.
167be7d mentions: Send user group mention data to notification notices.
07d6ab9 notification_data: Add get_user_group_mentions_data function.
ee424c1 push_notifications: Assert observation written in comment.
6bbfddb docs: Split widgets and slash command developer pages.
6785268 docs: Update developer documentation for
e196ea7 event_queue: Consistently user user_notifications_data as variable name.
733e0ae notification_data: Rename sender_id -> acting_user_id.
1cf1d14 event_queue: Move notification trigger logic to notification_data.
6619282 maybe_enqueue_notifications: Take in notification_data dataclass.
dedc39f notifications_data: Rename id -> user_id.
f6e705d maybe_enqueue_notifications: Require all keyword arguments.
226ac4b tornado: Use UserMessageNotificationsData for update_message.
c3fb413 message edit: Don't send mentioned user_ids in event dict.
c6d696c process_message_event: Deduplicate is_notifiable logic.
5c483e3 get_active_presence_idle_user_ids: Check notifiability more thoroughly.
aeb2ad5 notification_data: Annotate flags with Collection.
8182632 notification_data: Add methods to determine notifiability.
ed58393 message send: Optimize how user data is sent to Tornado.
6167c36 event_queue: Translation code for user data migration.
b6806fb message send: Calculate presence_idle_user_ids after building user data.
42e4fa7 message send: Refactor how user data is sent for the event.
3ff3ded process_message_event: Always calculate online_push_enabled.
951b49c message send: Introduce dataclass to wrap user-notifications variables.
2179275 event_queue: Deduplicate mentioned flag calculation.
40cd6b5 message send: Calculate wildcard_mention_notify pre-send_event.
919f0a5 message send: Extract local variables for user event data.
56f6656 message send: Don't create user data list with inline for.
5a642ce missedmessage_hook: Don't enqueue notificationss if sender is muted.
86a20c5 event queue: Always set internal_data flags.
5a36496 node tests: Use mock_template in typeahead_helper.
3c2dbf1 node tests: Use mock_template in subs.
9f857e5 node tests: Use mock_template in stream_edit.
1586907 node tests: Use mock_template in settings_user_groups.
de6988b node tests: Use mock_template in settings_profile_fields.
30023d4 node tests: Use mock_template in settings_org.
9e324c0 node tests: Use mock_template in popovers.
8a214c9 node tests: Use mock_template in drafts.
177eafb node tests: Use mock_template in compose_video.
b564d5c node tests: Use mock_template in compose_validate.
09f8a8e zjsunit: Clear require cache also for templates.
10dd5f7 event_queue: Don't check for "read" flag when processing events.
3fd53d6 test_email_notifications: Add test for "read" flag return.
2b438fd test_push_notifications: Fix incorrect "read" flag test.
c6a31dc event_queue: Extract local variables.
58da384 muting: Don't enqueue notifications for messages from muted senders.
006b92e message send: Plumb sender muters through get_recipient_info.
30c9934 test_message_edit_notifications: Cleanup irrelevant parameters.
2bbdd42 test_event_queue: Fill-up default data in missedmessage_hook tests.
d9395e7 test_event_queue: Introduce helper to fill-up default values.
8eec7b4 test_event_queue: Extract common data setup in check_will_notify.
b7fcb02 cache: Use ids instead of UserProfiles for get_muting_users.
5f5323b event_queue: Pass bools to maybe_enqueue_for_message_update.
22d1937 event_queue: Reorder maybe_enqueue_for_update parameters.
99b1816 actions: Create dataclass for message read events.
e33c410 actions: Use custom_profile_field as variable name, not field.
86d6872 onboarding: Select Message FOR UPDATE when adding reaction.
90b6fa7 reactions: Select Message FOR UPDATE when adding/removing.
efc2f49 submessage: Select Message FOR UPDATE when creating.
5f4113c message delete: Select Message FOR UPDATE when archiving.
1a9f385 access_message: Allow selecting message row FOR UPDATE.
51f5bbc test_events: Run on_commit send_event hooks immediately.
60464a4 tests: Run on_commit hooks immediately in tornado_redirected_to_list.
8b14704 test_classes: Fix misplaced tornado_redirected_to_list comment.
2489a1b test_event_queue: Don't use lists for call_args assertions.
f88b943 email_notifications: Remove unnecessary online_emails check.
44534ca refactor: Move receives_email_notifications tests to designated file.
3990b18 models: Remove unused receives_stream_notifications function.
518deb7 models: Rename receives_online_notifications function.
e11648f docs: Fix typo in subsystems/
7a4c212 test_subs: Add comments about num_events.
aa2fd15 tornado_redirected_to_list: Fix event list leaks in tests.
3039a01 tornado_redirected_to_list: Make expected_num_events required argument.
15f78ab message edit: Handle topic edit tries for private messages.
4b30fc0 message edit: Extract data validity checks from check_update_message.
10be798 message edit: Extract test helpers in their own class.
3d99292 message edit: Fix stream_id description in API docs.
c19b7b4 tests: Use tornado_redirected_to_list instead of mocking send_event.
090f2d6 test_helpers: Remove capture_event helper.
d2bc93f tests: Extract helper in test_user_status.
481a890 tests: Assert num_events in tornado_redirected_to_list.
f236a0d message send: Rename always_push_notify -> online_push_enabled.
ddd123f message send: Rename push_notify_user_ids -> online_push_user_ids.
8bcdbc7 tests: Move tornado_redirected_list to ZulipTestCase.
ec8a931 message send: Pass individual parameters instead of single Dict.
d6871db message send: Do not re-assign widget_content variable.
334db60 message send: Fix incorrect field types in SendMessageRequest class.
0ec905e custom_check: Enforce use of assert_length helper.
352634a tests: Consistently use assert_length helper.
4d45b45 test_classes: Generalize assert_length helper.

During application period (30 March 2021 to 17 May 2021, 71 commits)

9a64f74 help: Clarify what muting means for the muted user.
a377a2d pm_list: Use "Muted user" placeholder for muted usernames.
336b791 recent topics: Use tippy tooltip instead of HTML title.
ed8faf1 recent topics: Rename some HTML classes for readability.
e5a339d recent topics: Handle muted user avatars in participants.
e4cbfca recent senders: Rename sender_info getter function for brevity.
421cf05 people: Deduplicate get_full_names logic.
c637994 help: Fix typo in mute-a-user page.
67cd385 mute user: Add user documentation page.
9519221 mute user: Remove development environment checks.
35fb095 confirm dialog: Allow specifying /help links.
22053d8 people: User "Muted user" placeholder for muted usernames.
5bcc965 refactor: Extract people.get_display_full_names.
eadbce4 message list: Don't exclude 1:1 PMs with muted users in pm-with narrows.
a59f545 message lists: Exclude 1:1 PMs with muted users.
e64e593 message lists: Don't allow user/topic mute message filtering independently.
2fc87ec node tests: Prefer actual Filter instances over dummy objects.
65249d9 compose_typeahead: Exclude muted users from results.
04c355c typing notifications: Exclude muted typists.
47764de user muting: Add helpers to filter out muted users.
615e1f9 node tests: Clean up user_pill.js tests.
80ccfc7 docs: Fix outdated pre-ES6 function examples.
e4d5114 filter: Add new is_non_huddle_pm method.
9f6ad77 message view: Allow revealing hidden message from muted sender.
5d79698 message view: Hide messages sent by muted users.
7f9c3bb starred messages: Fix "unstar all in topic" is incomplete.
ded3d94 starred messages: Clean up "unstar all in topic" warning.
29bf973 message list: Stub with Error instead of asserting zero calls in tests.
4bd7ec7 message lists: Rename update_items_for_muting to include topic.
10cfd25 node tests: Remove redundant muting tests for message lists.
9d8bcce message_list: Don't store excludes_muted_topics twice.
15e3420 mute user: Hide from top left corner PM list.
615f79d node tests: Clean up data setup in pm_conversations.js.
6769990 node tests: Introduce test wrapper in pm_conversations.js.
fc53d2c topic muting: Clean up live update code.
2c4505d settings/muted-topic: Move list-create code to designated file.
eff16c9 settings/muted-topics: Fix unnecessary use of stopImmediatePropogation.
3e9b4a2 mute user: Hide from right sidebar users list.
4f9c688 buddy_data: Rename get_user_id_list to get_filtered_user_id_list.
aa47ca0 buddy_data: Move all user_id filtering code to filter_user_ids.
5860fb0 buddy_data: Move no filter text logic to filter_user_ids.
2c30b54 buddy_data: Move related functions to be together.
bbbaa10 settings: Add UI page for managing muted users.
e56db79 mute user: Add dev-only UI to mute/unmute a user.
1ffd8b0 ui: Use unicode U+2026 instead of literal "..." characters.
3947b0c linkifiers: Update API to send data using dictionaries.
2b9f2cc mute user: Add some comments on message fetch.
8b098b9 mute user: Mark as read old messages immediately.
2f56f8d mute user: Mark as read new messages.
b140c17 mute user: Cache list of muter IDs.
9602aa1 mute user: Record entries in RealmAuditLog.
e1acfb9 mute user: Fix incomplete API error responses in docs.
224a8e0 mute user: Add tests for realm import.
152508e mute user: Reduce two database fetches when unmuting to one.
32ab987 refactor: Use API instead of functions in
b500ff3 refactor: Respect example user conventions in
e912bee refactor: Use variables for dates in
1de9444 mute user: Add frontend functions to maintain data.
3bfcaa3 mute user: Add backend infrastructure code.
89f6139 mute user: Add model and makemigrations.
52a86d9 linkifiers: Use dictionaries for internal structures.
68fe912 refactor: Rename most of "filter" to "linkifier".
f896a76 refactor: Update some uses of "filter" to "linkifier".
a49dc67 refactor: Rename backend files to use "linkifier".
2698acd management: Fix incorrect help text in compare_messages.
9566369 refactor: Extract time calculation logic for topic muting.
f4c3ad5 refactor: Rename backend muting tests to be specific.
586f8fe refactor: Rename settings/muted-topics code to be specific.
3a9dfc0 refactor: Rename MessageList.update_muting_and_rerender.
f725711 recent topics: Fix live update on muted_topics events.
ace54f3 recent topics: Fix duplicate muting requests sent to server.

Before application period (Before 29 March 2021, 37 commits)

423770f refactor: Extract starred_messages_ui.js module.
42aea49 left sidebar: Add support to unstar all messages in topic.
f17a52b refactor: Use confirm_dialog for unstar-all-messages.
eb7b699 confirm_dialog: Make it usable outside settings.
1cc6f61 left sidebar: Fix exception on opening all/starred popovers.
a30ca84 refactor: Allow custom msg strs in send_message_moved_breadcrumbs.
91234b2 node tests: Add tests for starred_messages.js.
206fe1e node tests: Introduce message_store.create_mock_message() helper.
aa0e5dd refactor: Extract update message flags POST call.
b37e5cc left sidebar: Don't show unstar-all button when redundant.
a1e75ed linkifiers: Remove outdated comment in tests.
2ea330b linkifier settings: Remove loading indicator.
0acfbc3 linkifier settings: Fix empty list message not shown.
9223dce refactor: Rename filter to linkifier in frontend code and docs.
fc0488f actions: Rename notify_topic_moved_streams function.
674a5fe node tests: Split draft_model for add/edit/delete cases.
8cc0b43 node tests: Remove unecessary with_field call in pm_list.
6c6def2 node tests: Prefer override over with_field.
c183076 minor: Suggest with_field instead of override for non-functions.
a24d827 zjsunit: Remove with_stub helper.
0d770c3 node tests: Explicitly call make_stub.
9cb41c2 refactor: Extract excludes_muted_topics logic.
9ae44c7 refactor: Rename MessageList.muting_enabled.
e8b4902 node tests: Refactor muting test in message_list.
fd2bf0b refactor: Rename frontend muting stuff to include 'topic'.
5eec4b2 minor: Explicitly handle undefined date while muting a topic.
dbb69f7 settings: Fix message not shown in empty muted topics list.
e98a885 logging: Add logging in deferred_work queue processor.
bd61b57 stats: Fix strings passed to _() not translated.
a20d22d i18n: Move locale select logic in home to
b82bda9 stats: Fix i18n not working in stats page.
d9d51e3 i18n: Simplify logic for translation data in page_params.
4e6c098 stats: Fix a string not tagged for translation.
49fd272 invite: Fix compose box focus on clicking (Un)check All in invite window.
e5054a3 invite: Scroll to top and focus email input after submit in invite.js.
b570cf1 invite: Allow submitting invite form with Ctrl+Enter in invite.js.
9fc1047 invite: Focus first input in invite window in invite.js.

Acknowledgements and closing words

The last couple of months have been great! I learnt a lot of new things, and spent a really productive summer working on Zulip. I would like to thank my mentor, Ryan Rehman, for guiding me and helping me out when I was blocked on something. I would also like to thank Tim Abbott, Steve Howell and Mateusz Mandera for reviewing my work and pointing me towards the right resources for things which were new to me.

Overall, Google Summer of Code with Zulip has been an enriching experience for me, massively helping me improve as a developer. I look forward to remaining engaged with the Zulip community, helping out new contributors and also contributing more code, as far as possible, parallel to university work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment