New Messages in Other Rooms
Course 7 has four rooms Marcus may read: General, Team 4, Homework Help, and Off-Topic. Courselore shows one course at a time.
Marcus has Team 4’s room open. The room list on the side shows all four rooms. It shows a dot next to each room that has unread messages.
Marcus’s client keeps one long poll going for Team 4’s room:
GET /rooms/12/messages?after=61843
The server answers it only when a message is posted in Team 4’s room.
Now someone posts a message in General. Does a dot appear next to General on Marcus’s screen?
It does not. Marcus’s only long poll waits on Team 4’s room, so the server keeps it in Team 4’s list. When a message is posted in General, the server answers the requests in General’s list, and Marcus’s request is not there. The dot appears only when Marcus reloads the page and the client requests the room list again.
A long poll for each room
One fix is for Marcus’s client to keep a long poll going for each of the four rooms.
That works, but the server now keeps four requests for Marcus instead of one. The same goes for every other open client, so the server keeps four times as many requests. And every 30 seconds, four of Marcus’s requests time out instead of one.
There is a second problem, in the browser. Over HTTP/1.1, a browser opens only about six connections to one server. Each kept long poll occupies one of them. Marcus’s four long polls would take four of the six. If Marcus opens course 7 in a second tab, the long polls no longer fit. HTTP/2, a later version of HTTP, carries many requests on one connection, so with HTTP/2 that limit matters less. But the server still keeps four requests for Marcus.
One long poll for the course
Instead, Marcus’s client keeps one long poll going for the whole course:
GET /courses/7/updates?after=61843
The path names the course. The server knows who Marcus is from the request’s credentials, and so which rooms of course 7 Marcus may read: the course’s public rooms, and the private rooms Marcus is a member of.
after is the identifier of the newest message the client has from any of the four rooms. All rooms share one counter for message identifiers, so one number works for every room.
As with a long poll for one room, if any of those rooms already has a message after after, the server answers at once. Otherwise, the server keeps the request in the list of each of Marcus’s four rooms. When a message is posted in any of those rooms, the server answers the request. The server sends only one response to a request, so it then takes the request out of the other three lists.
The server keeps one request per open client again, no matter how many rooms there are.
The response
Someone posts in General. The server answers Marcus’s request with the new message. Each message says which room it belongs to:
{
"messages": [
{
"id": 61850,
"room_id": 11,
// other message attributes
}
]
}
Room 11 is General. The client looks at the room_id of each message:
- If it is the room Marcus has open, Team 4’s room, the client shows the message on the screen.
- If it is another room, here General, the client puts a dot next to that room in the room list.
Then the client sends the next request, with after=61850.
sequenceDiagram
participant A as Another student's client
participant S as Server
participant M as Marcus's client
M->>S: GET /courses/7/updates?after=61843
Note over S: nothing new, keeps the request
A->>S: POST /rooms/11/messages
S-->>A: 201, message 61850
S-->>M: 200, message 61850 in room 11
M->>S: GET /courses/7/updates?after=61850