|
|
Line 1: |
Line 1: |
| == What the Client Does==
| | #REDIRECT[[Services/Notifications/Push/Architecture]] |
| # Log in to Firefox with BrowserID. | |
| # Start Notifications client.
| |
| # Authenticate with Push Notification Service.
| |
| # Sync push URLs.
| |
| # Get stored messages.
| |
| # Get list of socket servers from Box Office.
| |
| # Connect to one of the socket servers, or backoff and retry.
| |
| # Get streaming messsages.
| |
| # Get new push URL (<tt>navigator.mozNotifcation.requestPermission()</tt>).
| |
| # Revoke push URLs (user action).
| |
| # Mark messages as read (synced with server).
| |
| # Maintain local DB of push URLs and site icons for displaying messages.
| |
| | |
| == Storage ==
| |
| Storage is keyed off a token generated from the BrowserID assertion. For each
| |
| user, we need to store a list of push URLs and a list of recent messages.
| |
| | |
| <b>Push URLs</b> need to be synced between user devices. They are persistent and
| |
| only deleted by user request.
| |
| | |
| <b>Recent messages</b> are stored on the server to support syncing messages
| |
| between devices. Messages will expire and be availble for garbage collection
| |
| after min(three days, sender-provided TTL). Clients can mark a message as read
| |
| after user action (clicking on a message or clearing it), and other clients will
| |
| update their local state.
| |
| | |
| NB: when I talk about sync I don't necessarily mean Sync.
| |
| | |
| == Server Components ==
| |
| All the good ideas are based off talks with Urban Airship. Each of the
| |
| following sections can be built as a separate component so that no one piece
| |
| can take down the whole system. They're partitioned based on the functionality
| |
| they provide.
| |
| | |
| === Client API ===
| |
| HTTP endpoint supporting basic client operations. Clients would come here on
| |
| startup to sync push URLs and stored messages. New push URLs are created when a
| |
| site asks for push permission.
| |
| | |
| * Register client
| |
| * Create/revoke push URLs
| |
| * Sync push URLs
| |
| * Get list of unread messages when a client comes online
| |
| | |
| === Third-party site API ===
| |
| HTTP endpoint supporting third-party sites. Notifications come into the system
| |
| and are passed on to the routing layer.
| |
| | |
| * Accept messages from third-party sites
| |
| * Pass messages to routing layer
| |
| | |
| === Routing Layer ===
| |
| When a messages comes in through the API it needs to be routed to the correct
| |
| socket server(s) to get pushed to a client. There may be zero, one, or many
| |
| connected clients. Routing possibilities:
| |
| * Registry server that tracks which socket server(s) a client is connected to, and then:
| |
| ** direct RPC to the socket server
| |
| ** pub/sub to a channel for that server
| |
| * Open pub/sub: all socket servers listen to the same channel and pick out which messages they can send
| |
| | |
| === Box Office (BO) ===
| |
| When a client wants to connect to a socket server, the client asks BO for a
| |
| list of server IP addresses. BO returns multiple IP addresses for the client
| |
| to connect to. The client should try them in the returned order (BO can order
| |
| by decreasing free capacity). If the client can't connect, it should get a
| |
| new list from the BO, using exponential backoff. If there are capacity
| |
| problems BO can tell a client not to connect to any socket servers.
| |
| | |
| This could potentially be merged into the Client API component.
| |
| | |
| === Socket Server ===
| |
| The socket servers hold open persistent client connections and pass messages to
| |
| sockets with minimal latency. They can't be behind Zeus due to licensing and
| |
| scalability issues.
| |
| | |
| * Hold connections open to clients
| |
| * Send messages to client
| |
| * Send message-read to client
| |
| * Receive message-read from client
| |
| * Send push URL updates to client?
| |
| * Track connection state and share with Box Office
| |
| * <b>Not behind Zeus</b>
| |