Aggregator Hubs, using WebSub Subscription Lists

Reduce feed polling, improve feed change notification reliability. Turn pollers into pushers!


Modify this proposal, Discuss this proposal


Current state

Aggregators, therefore, fallback to aggressive polling of every feed. The more aggregators there are, the more each feed is hammered, wasting resources and $$$.

Proposal

Perhaps the most important change to improve the current situation would be for podcast hosting companies to provide timely and reliable WebSub hubs for the feeds they control.

In the meantime, aggregators will be polling. Since they are already polling, they also know when feed contents change, and can offer to host their own hubs - turning polling into pushes! Federated apps & aggregators can delegate / rely on these intermediate hubs to lessen their own need to poll so aggressively, if only for a subset of feeds.

These new intermediate hubs, called Aggregator Hubs, should speak WebSub to each other instead of defining a new protocol - it is stable, well-documented, and already deals specifically with notification about web resource (“Topic URL”) updates.

In order to facilitate bulk subscription and delegation, this proposal defines subscription list resources that represent multiple underlying feed subscriptions. They are simple to implement (can be hosted static files), use WebSub and HTTPS for communication, and JSON for resource representation.

In general, Aggregator Hubs should follow the WebSub spec, with the following additional constraints:

There is nothing in this proposal that modifies or extends WebSub in any way, it just defines two well-defined subscribable resource types to standarize subscription list resources and their associated requests.

JSON is used to describe both resource types. This allows either party to fetch the current state of the resource, in case WebSub pings are dropped.

It is up to the hub whether or not they want to be subscribable by others, it is also up to the hub how they want to do authentication and authorization to limit subscribers. e.g. they might use a Bearer token or request signing.

It is up to the hub to define expected expiration dates for the WebSub subscriptions, or perhaps to disable expiration entirely for hub-to-hub communication.


Subscription List resources

Subscription List resources are named lists of feeds and corresponding underlying feed subscription status. These can either be created to correspond with a Subscription List Request from another party, or standalone named lists of feeds that the hub is watching.

Subscription Lists can be either static or dynamic:

Subscription List JSON objects have the following properties:

Example 1: Static Subscription List, no inclusion

https://hub2.fm/subscription-lists/b7244c0f-e3e3-4886-8aa5-55ef1ba2c0cf.json
Content-Type: application/json; charset=UTF-8
ETag: "24c5f1231737"
{
  "type": "static-subscription-list",
  "name": "Feeds to watch for Hub1",
  "modified": "2021-03-27T12:54:47.725Z",
  "self": "https://hub2.fm/subscription-lists/b7244c0f-e3e3-4886-8aa5-55ef1ba2c0cf.json",
  "hubs": [
    "https://websub.hub2.fm"
  ],
  "feeds": [
    { "url": "https://example1.com/feed1.xml", "status": 202, "level": 1, "frequency": "24" },
    { "url": "https://example2.com/feed2.xml", "status": 202, "level": 1, "frequency": "24" },
  ]
}

Example 2: Dynamic Subscription List

https://hub2.fm/subscription-lists/b7244c0f-e3e3-4886-8aa5-55ef1ba2c0cf.json
Content-Type: application/json; charset=UTF-8
ETag: "24c5f1231737"
{
  "type": "dynamic-subscription-list",
  "name": "All feeds managed by hub2.fm",
  "modified": "2021-03-27T12:54:47.725Z",
  "self": "https://hub2.fm/subscription-lists/b7244c0f-e3e3-4886-8aa5-55ef1ba2c0cf.json",
  "hubs": [
    "https://websub.hub2.fm"
  ],
}

Example 3: Static Subscription List with inclusion

https://hub2.fm/subscription-lists/b7244c0f-e3e3-4886-8aa5-55ef1ba2c0cf.json
Content-Type: application/json; charset=UTF-8
ETag: "d50d8036590b"
{
  "type": "static-subscription-list",
  "name": "Feeds to watch for Hub1",
  "modified": "2021-03-27T12:54:47.725Z",
  "self": "https://hub2.fm/subscription-lists/b7244c0f-e3e3-4886-8aa5-55ef1ba2c0cf.json",
  "hubs": [
    "https://websub.hub2.fm"
  ],
  "includes": [
    { "url": "https://hub2.fm/subscription-lists/sublist-1.json", "etag": "24c5f1231737" },
  ]
}

https://hub2.fm/subscription-lists/sublist-1.json
Content-Type: application/json; charset=UTF-8
ETag: "24c5f1231737"
{
  "type": "static-subscription-list",
  "name": "Feeds to watch for Hub1 - Sublist 1",
  "modified": "2021-03-27T12:54:47.725Z",
  "feeds": [
    { "url": "https://example1.com/feed1.xml", "status": 202, "level": 1, "frequency": "24" },
    { "url": "https://example2.com/feed2.xml", "status": 202, "level": 1, "frequency": "24" },
  ]
}

Subscription List Request resources

Subscription List Request resources are essentially named lists of feeds for another party to subscribe to. The other party uses the request list to create a corresponding Static Subscription List on their side.

Subscription List Request JSON objects have the following properties:

Example 1: Subscription List Request with inclusion

https://hub1.fm/subscription-list-requests/fab26f5a-6e21-4c8f-9651-0bc18b815817.json
Content-Type: application/json; charset=UTF-8
ETag: "b5d3971829c0"
{
  "type": "subscription-list-request",
  "name": "Delegated feeds for Hub2",
  "modified": "2021-03-26T22:54:47.725Z",
  "self": "https://hub1.fm/subscription-list-requests/fab26f5a-6e21-4c8f-9651-0bc18b815817.json",
  "hubs": [
    "https://websub.hub1.fm"
  ],
  "feeds": [
    { "url": "https://example1.com/feed1.xml", "frequency": "24" }
  ],
  "includes": [
    { "url": "https://hub1.fm/sublist-1.json", "etag": "b5d52dee01db" }
  ]
}

https://hub1.fm/sublist-1.json
Content-Type: application/json; charset=UTF-8
ETag: "b5d52dee01db"
{
  "type": "subscription-list-request",
  "name": "Delegated feeds for Hub2 - Sublist 1",
  "modified": "2021-03-26T12:54:47.725Z",
  "feeds": [
    { "url": https://example2.com/feed2.xml", "frequency": "24" }
  ]
}

Delegation scenario

Hub1 gives Hub2 a list of feeds to watch on its behalf

Alt Text

Agreement and setup, out of band (e.g. over email):

Subscription List Request URL and Subscription List URL should be capability URLs

Typical flow:


Dynamic Subscription List scenario: Podcast Host

A podcast hosting company could host a publicly-subscribable Subscription List resource for internet clients to listen for ALL changes to feeds managed by the host. In this case, no Subscription List Request is needed, and the Subscription List is logical only, would not need to enumerate all underlying feeds.


Dynamic Subscription List scenario: Notifications for logical feed groups

A smaller delegate Aggregator Hub could create a named Subscription List resource to notify a larger hub about feed changes it finds for the feeds it’s polling, without enumerating them. For example, it could notify the parent when it finds ANY change it knows the parent would care about, or a subset of feeds, say feeds that are known to produce new content hourly.


Examples


References


Modify this proposal, Discuss this proposal