Development blog for Kin

Tag: subscriptions

Rebuilding the notifications flow

It’ll probably be about 2AM until this post goes out, so if I am some sort babbling incoherent dingus, I apologise in advance. Have a kitty.

OK. So, notifications. What an absolute clusterfuck.

I’ll see if my sleepdeprived brain can somehow map out the idea and model we have for notifications in Kin. The challenge is to be able to logically group and display the notifications, so we don’t give people a heartattack when they log in and see the list of activity while they’ve been away.

The achieve that I am using a table called ‘secretprefix_notifications‘. Clever, right? It looks a little like this:

CREATE TABLE `notifications` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `contentID` int(11) DEFAULT NULL,
  `contentType` varchar(10) DEFAULT NULL,
  `senderID` int(11) DEFAULT NULL,
  `senderType` varchar(10) DEFAULT NULL,
  `recipientID` int(11) DEFAULT NULL,
  `recipientType` varchar(10) DEFAULT NULL,
  `url` longtext,
  `notificationType` varchar(100) DEFAULT NULL,
  `timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;

The two content tables can tell us which specific piece of content we’re targetting. The sender ID does the same and (along with the same model for recipients) allows us to target both Users and Pages. Finally the URL will allow me to create a redirect link, and so somewhat invisibly notifiy the system that the user has not only seen this notification, but also reacted to it.

Finally, we have the column, notificationType. This column dictates, essentially, which text string to output when listing the notifications. Stuff like “Frank, Janice and 4 others have reacted to your comment.”

But … who gets notifications?

That’s a good question, that no sane person would ask, because reasons.

Depending on the event that triggers the notification it might be as banal is just dumping in the notification directly between two users. We would do that for strictly one-to-one events, like anything friend request related (request, acceptance or rejection).

But for stuff like status updates there’s a real chance that I might have to send notifications to a ton of people.

To do that we have a subscription model, not unlike the Notification Subscription function Facebook has (in fact, Kin 1 had that functionality before Facebook … so suck it, Zuck). Whenever a user interacts with an update, in any way (which is essentially reacting to an update, comment on an update, or reacting to a comment on an update) we create a subscription for new activity on that piece of content for that specific user or page.

That is stored in an equally originally named table called ‘secretprefix_subscriptions‘ and it looks like this:

CREATE TABLE `subscriptions` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `postID` int(11) NOT NULL,
  `subscriberID` int(11) NOT NULL,
  `subscriberType` varchar(10) DEFAULT NULL COMMENT 'Can be either ''user'' or ''page''',
  `active` binary(1) DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `kin_subscriptions_idx` (`postID`,`subscriberID`,`active`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;

We make a query to that table, excluding the author of the current activity, and pass that to the Notification class, that then creates a notification for each subscriber. The logic itself is pretty straightforward, once broken down.

Next step … notification output and rendering. But that’s for another post. Now I need sleep.

When Notifications go awry

So, I am looking into implementing Notifications for Kin 2, and while I want to make certain improvements over Kin 1, it’s important that we also don’t make the same mistakes again.

In Kin 1 we had one very strange bug. Notifications send to a specific User might end up in the Notification Queue of a given Page, and vice versa. It’s been an ongoing issue for a long long time, and both I and other members of the Kin 1 team struggled to understand why that was happening.

Well, I think I figured it out.

But to properly explain I’m going to have to back up a bit.

The very first iteration of Kin lacked a lot of the more advanced stuff we have today. There were no Pages or Groups. We still wanted Notifications for when people interacted with Updates, so Daniel built a subscription model. Basically every single time someone interacted with an Update, a row would be inserted into the subscription table denoting whether or not they had subscribed to that piece of content. The table looked a little something like this:

CREATE TABLE `subscriptions` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `updateID` int(11) NOT NULL,
  `userID` int(11) NOT NULL,
  `active` binary(1) DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `subscriptions_idx` (`updateID`,`userID`,`active`)
) ENGINE=InnoDB AUTO_INCREMENT=5067 DEFAULT CHARSET=utf8;

The two columns ‘updateID‘ and ‘userIDconnects this table to the Updates table and the User table. The ‘active‘ column denotes whether or not the subscription is active.

This model had a lot of benefits. For instance, a User had the option of subscribing to an Update without interacting with it, essentially allowing people to lurk in a conversation and still be notified when something new happened.

What would happen is that whenever an interaction took place we would look at the Subscription table to determine who should receive a Notification. By polling on the ‘updateID‘ and ‘active‘ we could get a list of userID’s that were subscribed to notifications on this particular Update.

However, when the application grew, and specifically when we added Pages we added another set of parameters under which an Update could be posted. Essentially, once logged in you could “switch” to any of your characters Pages and then post as that page, with Updates having the pages logo and name in the Update, rather than that of the character.

What we, now obviously, forgot, was to add this functionality to the subscription model. All our tables have Primary Keys which we use to internally reference a bunch of data. But for this, essentially if a Page had Primary Key 11 in the Pages table and a User had Primary Key 11 in the Users table, those could get mixed up in the Subscriptions table, and presto there’s the crossed wires mess.

Now I present our new and improved Subscriptions table which hopefully (knock on wood) fixes this particular issue.

CREATE TABLE `subscriptions` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `postID` int(11) NOT NULL,
  `subscriberID` int(11) NOT NULL,
  `subscriberType` varchar(10) DEFAULT NULL COMMENT 'Can be either ''user'' or ''page''',
  `active` binary(1) DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `subscriptions_idx` (`postID`,`subscriberID`,`subscriberType`,`active`)
) ENGINE=InnoDB AUTO_INCREMENT=5067 DEFAULT CHARSET=utf8;

Now … onwards and upwards to Notifications. Which is probably going to make me hate life on a whole new level.

© 2020 Kin Social Platform

Theme by Anders NorenUp ↑