What is a event feed?
It’s a list of events on something that has happened. This is useful if we have two applications that need to share events between each other. But we don’t want to push the event to the receiving application. Instead we want the reviving application to pull the events instead. This allows us to be more loosely coupled, cause the application that is signaling the event just have to publish the event to the feed. That eases the error handling a lot.
The list of events will be strictly growing, so the events can not be changed or deleted. Such stream of events could be represented in a numbers of ways, from plain text to binary. But we could also use a standardized method for distributing such stream of events. It’s here the Atom Feed specification comes into the picture.
Implementation of the feed
Using Atom Feed specifications https://tools.ietf.org/html/rfc4287, https://www.ietf.org/rfc/rfc5023 and https://tools.ietf.org/html/rfc5005. Each event is embedded in exactly one entry. One such entry could use the same id as the event id as long as the id is unique for the feed. Such id could preferably be an UUID. The feed could also host different event divided by different categories.
An example of an empty feed
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title type="text">Title</title> <link rel="self" type="application/atom+xml" href="http://localhost:8080/api/feed/recent" /> <link rel="via" type="application/atom+xml" href="http://localhost:8080/api/feed/1" /> <id>urn:id:1</id> <updated>2017-12-11T13:05:39Z</updated> </feed>
As we see in this example, the feed itself has an own id, last updated and a couple of links. The links in this case links back to the feed itself, both by the current address and the via relation that describes the absolute address for this particular feed. It may have links to navigate to next or previous archive and also to the beginning or the end of the feed.
If we add the simplest form of entry to this feed it looks like this:
<entry> <id>urn:id:1</id> <title>Title</title> <updated>2017-12-11T13:10:39Z</updated> <link rel=”alternate” href="http://localhost:8080/api/resource/1" /> </entry>
The id, title and updated elements are all mandatory. The id in this case must be unique for the entire feed, in this case we may have used an incremental counter. A better solution can be to use a globally unique identifier like an UUID. The entry could have one content element. In that content element may preferably used to host the content of our event. This could be done by serializing the event to a xml representation that is put into the content.
If the content is not used, the entry must have a link with the rel=”alternate” that points to a resource where it is possible to get the event or content for the event.
Also the entry has a category element. This can be used to categories the different events that are being represented on the feed. It can also be used to search the feed for some type.
Thin and fat feeds
When we think of how we want do distribute the content on our feed we need to determine if we want to use a thin or fat representation of an event. This is a decision that needs to be done together with the consumer of the feed.
A thin event is represented with minimum a link where we can get the representation of the event or content that the event signals a change for. This offer a great freedom when it comes to versioning, because we can easily just redirect the call to that resource to the new version. But the downside is that it don’t describe what in that resource that have changed. This may cause the consuming system to re-fetch the data with uninteresting changes.
Fat events on the other hand describes in detail what the change consists of without fetching any more data. The downside in this case is the versoning of such feed. Cause if we change the format, how should we change the already stored feed?
Versioning of the feed
If the event is distributed inside the content part of the entry, one solution could be to simply have both the new and the old event type on the feed until all consumers of the feed have conformed to the new version. One hard thing to managed is if we are using this feed as an event sourcing architecture, in that case we actually need to rewrite the old events to the new version, or both version, and therefor breaking the rule of events must not be changed. This is allowed anyway as long as the entries don’t change order an still contains the same information (depending on the version upgrade in that case).
Demo application of events on a feed
There is a good demo application that can be used to simulate a system that distributes its events onto a feed. That application can be retrieved at the following link https://github.com/SUNET/simone-example.
The good thing about this application is that it comes preloaded with a simple coffee shop example that can be run directly as an docker image. It also uses swagger to visualize the rest api on the example application.