Let's say you are writing a mobile application which allows users to invite their friends via Facebook, Gmail, and services like those. To make things concrete, let's say your application lets users create shopping lists for parties, and lets users link to their Facebook and Gmail accounts.
So Farah gets the app, links her Facebook account, creates a shopping list and invites her friend Priya to collaborate on it. By linking to Facebook, she is able to access her Facebook friend list of which Priya is a member, so that's how she sends the invitation.
Priya gets a message from Farah in her Facebook mailbox. Here's what we want to have happen:
So Farah gets the app, links her Facebook account, creates a shopping list and invites her friend Priya to collaborate on it. By linking to Facebook, she is able to access her Facebook friend list of which Priya is a member, so that's how she sends the invitation.
Priya gets a message from Farah in her Facebook mailbox. Here's what we want to have happen:
- If Priya already has the app, and has linked her Facebook account, she automatically sees the invitation when she next opens the app,
- If she doesn't have the app, she will download it (by following the app-store link conveniently included in the Facebook message) and link her Facebook account. When she does that, the invitation will appear in the app.
How can we do this? Here's my solution which is simple and easy.
The app's server will maintain two types of user objects - active users and passive users. An active user is one who has downloaded the app and registered as a user. A passive user is someone to whom an invitation has been sent, but who may not have downloaded the app yet.
Active user objects have a (possibly empty) set of linked external accounts. A passive user object will contain exactly one linked account.
When Farah sends Priya the message, the system will look for an active user object containing a linked account for Priya@Facebook. If it finds one, it associates the invitation to that user object so that Priya sees it the next time she logs in.
If there is no active user, the system will look for a passive user. If it finds one, it will associate the invitation to it, and if not, it creates one and associates the invitation to the new object.
When Priya finds and downloads the app, she will hopefully link her Facebook account. At this time the system will look for passive users attached to her Facebook account. When it finds it (and there should be only one), it will link the newly created active object to this pre-existing passive object, and via the passive user will gain access to all associated invitations.
Since the passive user object is not removed from the system, no lists containing it need to be updated. So Farah's party list will continue to hold a reference to the passive object, and when the system asks for the user it will "follow the links" to the active object.
Since the passive object acts only as a forwarding mechanism now, the information about the linked Facebook account can be moved to the active object to avoid wastage of space. And in fact we don't need to hold on to the passive object at all - we could just maintain a mapping from the passive object IDs to the active ones. So a "getUser" function would look like
Note that multiple passive objects could link to a single active object - this would happen if someone received invitations via multiple services. When they link those services this mechanism will pull all that passive activity over to the active account, which is just what we want.
If there is no active user, the system will look for a passive user. If it finds one, it will associate the invitation to it, and if not, it creates one and associates the invitation to the new object.
When Priya finds and downloads the app, she will hopefully link her Facebook account. At this time the system will look for passive users attached to her Facebook account. When it finds it (and there should be only one), it will link the newly created active object to this pre-existing passive object, and via the passive user will gain access to all associated invitations.
Since the passive user object is not removed from the system, no lists containing it need to be updated. So Farah's party list will continue to hold a reference to the passive object, and when the system asks for the user it will "follow the links" to the active object.
Since the passive object acts only as a forwarding mechanism now, the information about the linked Facebook account can be moved to the active object to avoid wastage of space. And in fact we don't need to hold on to the passive object at all - we could just maintain a mapping from the passive object IDs to the active ones. So a "getUser" function would look like
getUser(userId)
{
if(userId in passiveToActive.keys)
userId = passiveToActive[userId]
return db.findUserObj(userId);
}
Note that multiple passive objects could link to a single active object - this would happen if someone received invitations via multiple services. When they link those services this mechanism will pull all that passive activity over to the active account, which is just what we want.