FeedSync Implementation Notes

Originally published at http://dev.live.com/feedsync/spec/implnotes.aspx

About this document

This document is a companion for the FeedSync specification. The implementation notes here provide extra details about how implementers should interpret the FeedSync specification, and provide guidance for how to write a correct implementation.

This document is not intended to subsume the FeedSync spec. In any case where there may be ambiguity between this document and the spec, the FeedSync specification is the authoritative reference.

Contents

Note 1: Incorporating new and updated information

As described in the overview, the goal of FeedSync is to enable loosely cooperating endpoints to share a consistent set of data items through feeds. Since feeds have information that is specific to the server that is publishing the feed, we don’t expect two servers to produce exactly the same feed.

Instead, there is a subset of information in the feed that will be identical regardless of which endpoint is publishing the feed. This means that endpoints need to observe certain rules when incorporating a feed into their local stores. Those rules are described in this note.

Child elements of a feed item into one of two categories:

When an endpoint incorporates incoming items, it may change the publisher-specific data without updating the synchronization metadata for the item. However, endpoints must not change shared data without updating the synchronization metadata for the item.

Let’s take a look at a hypothetical example. Suppose “endpoint-a” produces this feed:

<?xml version="1.0" encoding="utf-8"?>
 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:sx="http://feedsync.org/2007/feedsync">
   <title>endpoint-a’s To Do List</title>
   <link rel="self" href="http://endpoint-a/feed.xml"/>
   <updated>2008-08-05T11:43:33Z</updated>
   <id>urn:uuid:00000000-1111-1111-1111-000000000000</id>
   <entry>
    <title>Buy groceries</title>
    <content>Get milk, eggs, butter and bread</content>
    <id>urn:uuid:00000000-0000-0000-0000-000000001234</id>
    <author>
         <name>Ray Ozzie</name>
    </author>
    <updated>2008-08-05T11:43:33Z</updated>
    <link rel=”edit” href=”
http://endpoint-a/item_1_myapp_2005-08-05T11:43:33Z” />
    <sx:sync id="item_1_myapp_2008-08-05T11:43:33Z" updates="3">
         <sx:history sequence="1" when="2008-08-05T11:43:33Z" by="REO1750"/>
    </sx:sync>
   </entry>
 </feed>

There are several elements in the feed that are conceptually “owned” by the publisher, endpoint-a; those are the ones we consider publisher-specific. For instance, the edit link in the entry points to endpoint-a. Another endpoint probably wouldn’t want to re-publish that link; instead, it would publish the same shared data such as the title and content, and replace the publisher-specific data with its own version.

Some other examples:

The incorporating endpoint can make any of these changes to publisher-specific data without updating the synchronization metadata in the entry.

Getting back to the example, assume that endpoint-b has incorporated the feed above. Assuming that it makes no changes to the data, and is just republishing the data in its own feed, here’s what endpoint-b’s feed might look like:

<?xml version="1.0" encoding="utf-8"?>
 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:sx="http://feedsync.org/2007/feedsync">
   <title>endpoint-b’s To Do List</title>
   <link rel="self" href="http://endpoint-b/todofeed.xml"/>
   <updated>2008-08-05T12:00:00Z</updated>
   <id>urn:uuid:00000000-2222-2222-2222-000000000000</id>
   <entry>
    <title>Buy groceries</title>
    <content>Get milk, eggs, butter and bread</content>
    <id>urn:uuid:00000000-0000-0000-1234-000000000000</id>
    <author>
         <name>ray@example.com</name>
    </author>
    <updated>2008-08-05T12:00:00Z</updated>
    <link rel=”edit” href=”
http://endpoint-b/myapp/item1/” />
    <sx:sync id="item_1_myapp_2008-08-05T11:43:33Z" updates="3">
         <sx:history sequence="1" when="2008-08-05T11:43:33Z" by="REO1750"/>
    </sx:sync>
   </entry>
 </feed>

Note the similarities and differences:

General rules

Here are the general rules to follow.

In an Atom feed, the following child elements of an entry must be considered shared data:

In an RSS feed, the following child elements of an item must be considered shared data:

Any child elements of the entry or item that are not defined by the feed format or by this specification should be considered shared data.

Anything that doesn’t fit one of the categories above should be considered publisher-specific data, unless the publisher explicitly states otherwise. Typically, this means that if an element is defined in the feed format specification, and is not listed above, then it is considered to be publisher-specific.

We recommend that endpoints do not require publisher-specific data to be exchanged between endpoints. When publisher-specific data is submitted to a remote endpoint, the submitter should not expect the same values to be returned, as shown in the examples above. We strongly recommend that feed publishers document any ways in which their implementation differs from these guidelines.

Note 2: Multiple entries with the same atom:id

This note subsumes a paragraph in the v1.0 spec that was removed from v1.0.1. The specific paragraph was the second note in the definition of the sx:sync/@id attribute in section 2.4, dealing with feeds that contain multiple entries with the same atom:id value.

The Atom spec specifically allows multiple entries in the same feed to have the same atom:id, as described in section 4.1.1: “If multiple atom:entry elements with the same atom:id value appear in an Atom Feed Document, they represent the same entry. Their atom:updated timestamps SHOULD be different.”

The RSS 2.0 specification doesn’t specifically address this case, but presumably most feed consumers would also treat these as different versions of the same item.

This case is unlikely to come up in a FeedSync implementation. One reason is that the intent of FeedSync is to allow endpoints to exchange their current state, as opposed to exchanging a series of state changes. For example, consider the case where you’re synchronizing a collection of contacts. You might make hundreds of changes on an endpoint, but another endpoint asking for the FeedSync feed would only receive the current state of each endpoint. (This has the advantage of being more efficient as well.)

For that reason, it’s unlikely to see a FeedSync feed that has a repeated item. However, FeedSync doesn’t disallow having a feed with multiple entries or items with the same id. We would expect the same case as described in the Atom spec: those elements represent different versions of the same entry.

We’d also expect that when those entries (or RSS items) are merged with the FeedSync merge algorithm, one of the entries SHOULD subsume the other. The merge should not result in a conflict between the two items, because that would mean that the same endpoint had produced conflicting versions of an item, which would be an implementation error.