1
0
mirror of https://github.com/moparisthebest/xeps synced 2025-02-16 07:10:15 -05:00

Address some feedback on entity versioning

This commit is contained in:
Sam Whited 2015-09-02 19:55:22 -05:00 committed by Matthew A. Miller
parent f7eb0a8a8c
commit 8c40f32172

View File

@ -144,8 +144,7 @@
</section2> </section2>
</section1> </section1>
<section1 topic='Protocol' anchor='proto'> <section1 topic='Discovering Support' anchor='disco'>
<section2 topic='Discovering Support' anchor='disco'>
<p> <p>
If a server supports entity versioning, it MUST inform the connecting If a server supports entity versioning, it MUST inform the connecting
client when returning stream features during the stream negotiation client when returning stream features during the stream negotiation
@ -166,34 +165,34 @@
The entity versioning stream feature is merely informative and therefore The entity versioning stream feature is merely informative and therefore
is never mandatory-to-negotiate. is never mandatory-to-negotiate.
</p> </p>
</section2> </section1>
<section2 topic='Version Tokens' anchor='version_tokens'> <section1 topic='Version Tokens' anchor='version_tokens'>
<p> <p>
Version tokens are short case-sensitive strings which are generated by Version tokens are short case-sensitive strings which are generated by the
the server. Their format is not defined in this spec, but a server. Their format is not defined in this spec, but a recommendation may
recommendation may be found in the Implementation Notes. Version tokens be found in the <link url="#impl">Implementation Notes</link>. Version
are akin to a weakly-validated etag for the entity in question. tokens are akin to a weakly-validated etag for the entity in question.
</p> </p>
<p> <p>
Servers that implement this protocol must assign such a version token to Servers that implement this protocol must assign such a version token to
each entity that is controlled by the server. The server MUST then update each entity that is controlled by the server. The server MUST then update
this version every time any mutable property of the entity changes (eg. this version every time any mutable property of the entity changes (eg.
when the subscription status of a user changes). The server MAY choose to when the subscription status of a user changes). The server MAY choose to
update this token at any time (to force the clients to invalidate their update this token at any time (to force the clients to invalidate their
cached representation fo the object). This version token MUST then be cached representation fo the object). This version token MUST then be
included with every object representation of that entity sent down in the included with every object representation of that entity sent down in the
stream. This is done by including a sub-node called "version" qualified stream. This is done by including a sub-node called "version" qualified
by the entity versioning XML namespace defined in this document. by the entity versioning XML namespace defined in this document.
Similarly, clients MAY also add version nodes for each version token they Similarly, clients MAY also add version nodes for each version token they
possess to the request for a list (not specifying a version token will possess to the request for a list (not specifying a version token will
force the server to send information on that entity to the client). If a force the server to send information on that entity to the client). If a
server sends up a list of version tokens, the server MUST then check to server sends up a list of version tokens, the server MUST then check to
see if those tokens correspond to any entity which it knows about, and see if those tokens correspond to any entity which it knows about, and
not send down any entities with matching version tokens in the response. not send down any entities with matching version tokens in the response.
</p> </p>
<p>For example, a roster request might look like:</p> <p>For example, a roster request might look like:</p>
<example caption="Roster Request"><![CDATA[ <example caption="Roster Request"><![CDATA[
<!-- Client --> <!-- Client -->
<iq from='romeo@montague.lit/home' id='56' to='romeo@montague.lit' type='get'> <iq from='romeo@montague.lit/home' id='56' to='romeo@montague.lit' type='get'>
<query xmlns='jabber:iq:roster'> <query xmlns='jabber:iq:roster'>
@ -271,53 +270,54 @@
Clients that implement this protocol SHOULD then cache the entity in Clients that implement this protocol SHOULD then cache the entity in
question when a version token is received. question when a version token is received.
</p> </p>
</section2>
<section2 topic='Cache Invalidation' anchor='deletes'>
<p>
When a client syncs with the server and indicates that it has a version
token in its cache that does not match any entity on the server (or when
the server wants to remove an entity from the clients cache for any other
reason), the server MUST reply with an empty &lt;version/&gt; node. When
the client receives such an empty version node it SHOULD purge the entity
from its cache. For example, the following exchange would trigger the
removal of 'inverness@chat.shakespeare.lit' from the cached MUC list:
<example caption="MUC deletion"><![CDATA[ <section2 topic='Cache Invalidation' anchor='deletes'>
<!-- Client --> <p>
<iq from='hag66@shakespeare.lit/phone' When a client syncs with the server and indicates that it has a version
token in its cache that does not match any entity on the server (or when
the server wants to remove an entity from the clients cache for any other
reason), the server MUST reply with an empty &lt;version/&gt; node. When
the client receives such an empty version node it SHOULD purge the entity
from its cache. For example, the following exchange would trigger the
removal of 'inverness@chat.shakespeare.lit' from the cached MUC list:
<example caption="MUC deletion"><![CDATA[
<!-- Client -->
<iq from='hag66@shakespeare.lit/phone'
id='zb8q41fas6yn4'
to='chat.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items>
<item jid='coven@chat.shakespeare.lit'>
<version xmlns='urn:xmpp:entityver:0'>25P2A7H8</version>
</item>
<item jid='inverness@chat.shakespeare.lit'>
<version xmlns='urn:xmpp:entityver:0'>4OLGSVNY</version>
</item>
</query>
</iq>
<!-- Server -->
<iq from='chat.shakespeare.lit'
id='zb8q41fas6yn4' id='zb8q41fas6yn4'
to='chat.shakespeare.lit' to='hag66@shakespeare.lit/phone'
type='get'> type='result'>
<query xmlns='http://jabber.org/protocol/disco#items> <query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='coven@chat.shakespeare.lit'> <item jid='inverness@chat.shakespeare.lit'>
<version xmlns='urn:xmpp:entityver:0'>25P2A7H8</version> <version xmlns='urn:xmpp:entityver:0'/>
</item> </item>
<item jid='inverness@chat.shakespeare.lit'> </query>
<version xmlns='urn:xmpp:entityver:0'>4OLGSVNY</version> </iq>
</item> ]]></example>
</query> </p>
</iq> <p>
If the client receives an indication that it should delete an item from a
<!-- Server --> list by any other means (eg. via a roster push), it SHOULD remove the
<iq from='chat.shakespeare.lit' version token associated with that entity from its cache.
id='zb8q41fas6yn4' </p>
to='hag66@shakespeare.lit/phone' </section2>
type='result'> </section1>
<query xmlns='http://jabber.org/protocol/disco#items'> <section1 topic='Aggregate Tokens' anchor='agg_tokens'>
<item jid='inverness@chat.shakespeare.lit'>
<version xmlns='urn:xmpp:entityver:0'/>
</item>
</query>
</iq>
]]></example>
</p>
<p>
If the client receives an indication that it should delete an item from a
list by any other means (eg. via a roster push), it SHOULD remove the
version token associated with that entity from its cache.
</p>
</section2>
<section2 topic='Aggregate Tokens' anchor='agg_tokens'>
<p> <p>
While the version token approach to caching does not require a great deal While the version token approach to caching does not require a great deal
of state to be stored on the client or the server, it does require a lot of state to be stored on the client or the server, it does require a lot
@ -327,9 +327,11 @@
avoid sending the large request entirely). To do this, we can request an avoid sending the large request entirely). To do this, we can request an
aggregate version token from the server. This aggregate token is calculated aggregate version token from the server. This aggregate token is calculated
by constructing a string of comma separated "bare JID:version" pairs sorted by constructing a string of comma separated "bare JID:version" pairs sorted
in byte-wise order, and taking the MD5 hash of the constructed string. For in byte-wise order (because the JID:version pair is constructed before
example, if the server is calculating the aggregate version token for a sorting, if two items in the list have the same JID they can still be
roster, it might end up with the following string: sorted by the version token), and taking the MD5 hash of the constructed
string. For example, if the server is calculating the aggregate version
token for a roster, it might end up with the following string:
</p> </p>
<example caption="Aggregate token list"><![CDATA[ <example caption="Aggregate token list"><![CDATA[
anne@shakespeare.lit:VIZSVF0D,bill@shakespeare.lit:25P2A7H8 anne@shakespeare.lit:VIZSVF0D,bill@shakespeare.lit:25P2A7H8
@ -344,25 +346,26 @@ anne@shakespeare.lit:VIZSVF0D,bill@shakespeare.lit:25P2A7H8
The actual request is an IQ sent to the server, or entity handling the The actual request is an IQ sent to the server, or entity handling the
versioned list which contains a query that specifies the namespace of the versioned list which contains a query that specifies the namespace of the
list we want to fetch. Eg. to fetch the aggregate token for the roster one list we want to fetch. Eg. to fetch the aggregate token for the roster one
would query the server: would query the server with the type set to the `jabber:iq:roster`
namespace:
</p> </p>
<example caption="Roster aggregate token request"><![CDATA[ <example caption="Roster aggregate token request"><![CDATA[
<!-- Client -->
<iq to='bill@shakespeare.lit' type='get' id='bill1'>
<query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster' />
</iq>
<!-- Client --> <!-- Server -->
<iq to='bill@shakespeare.lit' type='get' id='bill1'> <iq to='bill@shakespeare.lit/home' type='result' id='bill1'>
<query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster' /> <query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster'>
</iq> 0514fc90e6c7981b06bbb2173bb8ef03
</query>
<!-- Server --> </iq>
<iq to='bill@shakespeare.lit/home' type='result' id='bill1'>
<query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster'>
0514fc90e6c7981b06bbb2173bb8ef03
</query>
</iq>
]]></example> ]]></example>
<p> <p>
Similarly, to fetch the aggregate token for a list of MUC rooms, one would Similarly, to fetch the aggregate token for a list of MUC rooms, one would
query the MUC component directly: query the MUC component directly with the type set to the 'disco#items'
namespace:
</p> </p>
<example caption="MUC rooms aggregate token request"><![CDATA[ <example caption="MUC rooms aggregate token request"><![CDATA[
<!-- Client --> <!-- Client -->
@ -382,13 +385,18 @@ anne@shakespeare.lit:VIZSVF0D,bill@shakespeare.lit:25P2A7H8
to a normal request if any error is returned in response to an aggregate to a normal request if any error is returned in response to an aggregate
token IQ. token IQ.
</p> </p>
<p>
If an aggregate token is requested for a list that may contain more than
one type of entity (eg. MUC rooms and pubsub nodes that live on the same
component), then the server MUST return the aggregate token constructed
with the entire list (rooms and pubsub nodes).
</p>
<p> <p>
Clients are also NOT REQUIRED to check aggregate tokens. However, clients Clients are also NOT REQUIRED to check aggregate tokens. However, clients
MAY wish to check aggregate tokens before making a roster or MUC request MAY wish to check aggregate tokens before making a roster or MUC request
when the cached roster or MUC list is very large. When to check aggregate when the cached roster or MUC list is very large. When to check aggregate
tokens is left up to the clients. tokens (if at all) is left up to the implementation.
</p> </p>
</section2>
</section1> </section1>
<section1 topic='Implementation Notes' anchor='impl'> <section1 topic='Implementation Notes' anchor='impl'>