Description
Currently, in order for an application to receive updates from a channel, it needs to send a request to /api/v1/channels/latest/:ucid
or similar endpoint. This is inefficient when the number of channels being requested reaches even moderate size. This propsal is for a /api/v1/notifications
that uses EventSource to push notifications in near real-time.
The EventSource protocol pushes updates using a persistent connection to an HTTP server. It is supported in all major browsers with a polyfill available for IE. The EventSource API can automatically reconnect to the source on errors, and provides a simple API for handling events. There is also a wrapper reconnecting-eventsource for handling more challenging network conditions.
The EventSource protocol is quite simple and can be implemented easily in any language where it isn't already supported. It sends comments (lines prefixed with :
), or events containing: one or more data
fields, an optional id
, and an optional type
. After each message is sent a trailing newline. Example from the spec:
: test stream
data: first event
id: 1
data:second event
id
data: third event
/api/v1/notifications
The endpoint /api/v1/notifications
would support a topics
parameter containing a list of comma-separated resources. Each resource would be a UCID or any other supported ID. /api/v1/notifications
would support a maximum of 1000 topics per call.
Opening a connection to /api/v1/notifications
creates a persistent connection between the server and the client, with :keepalive #{TIMESTAMP}
messages sent every 20-30 seconds to ensure the connection is not dropped.
Each event would contain a data
field with the updated resource as JSON. Schema would be the same as /api/v1/channels/latest/:ucid
.
Example output from cURL:
$ curl https://invidio.us/api/v1/notifications?topics=UCAAAA,UCBBBB
:keepalive 1554427320
id: 0
data: {"title":"...","videoId":"AAAAAAAAAAA","author":"...","authorId":"UCAAAA","authorUrl":"/channel/UCAAAA","videoThumbnails":[{"quality":"...","url":"...","width":120,"height":90}],"description":"...","descriptionHtml":"<div>...</div>","viewCount":1,"published":1554474212,"publishedText":"1 days ago","lengthSeconds":10,"liveNow":false,"paid":false,"premium":false}
:keepalive 1554427333
:keepalive 1554427335
id: 1
data: {"title":"...","videoId":"BBBBBBBBBBB","author":"...","authorId":"UCBBBB","authorUrl":"/channel/UCBBBB","videoThumbnails":[{"quality":"...","url":"...","width":120,"height":90}],"description":"...","descriptionHtml":"<div>...</div>","viewCount":1,"published":1554474212,"publishedText":"1 days ago","lengthSeconds":10,"liveNow":false,"paid":false,"premium":false}
Example handling in JavaScript:
var notifications = new EventSource('https://invidio.us/api/v1/notifications?topics=UCAAAA,UCBBBB');
notifications.onmessage(event) {
var notification = JSON.parse(event.data); // => {title: "...", videoId: "AAAAAAAAAAA", ...
// Update feed, notify user, or any other necessary handling for the event
}
Polling for notifications after being offline
In order for an application to receive notifications after being offline , a ?since=TIMESTAMP
should be added to /api/v1/channels/latest/:ucid
. Using ?since=
would return up to 15 videos uploaded after the specified timestamp. If there are more than 15 videos that have been uploaded since the given date, /api/v1/channels/latest/:ucid
will return the 15 latest.
It may also make sense to support an ?until=TIMESTAMP
to create a "window" where specific videos can be queried, although this would require authentication as mentioned below.
Final thoughts
Notifications would only be supported for channels tracked by the instance, which means that one or more users on that instance are subscribed to them. Requesting that a new channel be tracked by an instance must be authenticated to prevent abuse. Authentication will be handled in a second RFC.
Important to note is that notifications will be sent when a channel changes a video's description or title, not just when it is uploaded.
In accordance with this spec, a "protocols":["eventsource"]
field should be added to /api/v1/stats
, example. See also #356.
I would like to discuss if there are any issues with this approach, or any other issues that haven't been considered to ensure this is provides as much utility as possible.
Thanks!