mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-21 16:55:07 -05:00
Address some feedback on entity versioning
This commit is contained in:
parent
f7eb0a8a8c
commit
8c40f32172
@ -144,8 +144,7 @@
|
||||
</section2>
|
||||
</section1>
|
||||
|
||||
<section1 topic='Protocol' anchor='proto'>
|
||||
<section2 topic='Discovering Support' anchor='disco'>
|
||||
<section1 topic='Discovering Support' anchor='disco'>
|
||||
<p>
|
||||
If a server supports entity versioning, it MUST inform the connecting
|
||||
client when returning stream features during the stream negotiation
|
||||
@ -166,34 +165,34 @@
|
||||
The entity versioning stream feature is merely informative and therefore
|
||||
is never mandatory-to-negotiate.
|
||||
</p>
|
||||
</section2>
|
||||
</section1>
|
||||
|
||||
<section2 topic='Version Tokens' anchor='version_tokens'>
|
||||
<p>
|
||||
Version tokens are short case-sensitive strings which are generated by
|
||||
the server. Their format is not defined in this spec, but a
|
||||
recommendation may be found in the Implementation Notes. Version tokens
|
||||
are akin to a weakly-validated etag for the entity in question.
|
||||
</p>
|
||||
<p>
|
||||
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
|
||||
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
|
||||
update this token at any time (to force the clients to invalidate their
|
||||
cached representation fo the object). This version token MUST then be
|
||||
included with every object representation of that entity sent down in the
|
||||
stream. This is done by including a sub-node called "version" qualified
|
||||
by the entity versioning XML namespace defined in this document.
|
||||
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
|
||||
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
|
||||
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.
|
||||
</p>
|
||||
<p>For example, a roster request might look like:</p>
|
||||
<example caption="Roster Request"><![CDATA[
|
||||
<section1 topic='Version Tokens' anchor='version_tokens'>
|
||||
<p>
|
||||
Version tokens are short case-sensitive strings which are generated by the
|
||||
server. Their format is not defined in this spec, but a recommendation may
|
||||
be found in the <link url="#impl">Implementation Notes</link>. Version
|
||||
tokens are akin to a weakly-validated etag for the entity in question.
|
||||
</p>
|
||||
<p>
|
||||
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
|
||||
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
|
||||
update this token at any time (to force the clients to invalidate their
|
||||
cached representation fo the object). This version token MUST then be
|
||||
included with every object representation of that entity sent down in the
|
||||
stream. This is done by including a sub-node called "version" qualified
|
||||
by the entity versioning XML namespace defined in this document.
|
||||
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
|
||||
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
|
||||
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.
|
||||
</p>
|
||||
<p>For example, a roster request might look like:</p>
|
||||
<example caption="Roster Request"><![CDATA[
|
||||
<!-- Client -->
|
||||
<iq from='romeo@montague.lit/home' id='56' to='romeo@montague.lit' type='get'>
|
||||
<query xmlns='jabber:iq:roster'>
|
||||
@ -271,53 +270,54 @@
|
||||
Clients that implement this protocol SHOULD then cache the entity in
|
||||
question when a version token is received.
|
||||
</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 <version/> 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'
|
||||
<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 <version/> 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'
|
||||
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'
|
||||
to='hag66@shakespeare.lit/phone'
|
||||
type='result'>
|
||||
<query xmlns='http://jabber.org/protocol/disco#items'>
|
||||
<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'>
|
||||
to='hag66@shakespeare.lit/phone'
|
||||
type='result'>
|
||||
<query xmlns='http://jabber.org/protocol/disco#items'>
|
||||
<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>
|
||||
</section1>
|
||||
<section1 topic='Aggregate Tokens' anchor='agg_tokens'>
|
||||
<p>
|
||||
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
|
||||
@ -327,9 +327,11 @@
|
||||
avoid sending the large request entirely). To do this, we can request an
|
||||
aggregate version token from the server. This aggregate token is calculated
|
||||
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
|
||||
example, if the server is calculating the aggregate version token for a
|
||||
roster, it might end up with the following string:
|
||||
in byte-wise order (because the JID:version pair is constructed before
|
||||
sorting, if two items in the list have the same JID they can still be
|
||||
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>
|
||||
<example caption="Aggregate token list"><![CDATA[
|
||||
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
|
||||
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
|
||||
would query the server:
|
||||
would query the server with the type set to the `jabber:iq:roster`
|
||||
namespace:
|
||||
</p>
|
||||
<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 -->
|
||||
<iq to='bill@shakespeare.lit' type='get' id='bill1'>
|
||||
<query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster' />
|
||||
</iq>
|
||||
|
||||
<!-- Server -->
|
||||
<iq to='bill@shakespeare.lit/home' type='result' id='bill1'>
|
||||
<query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster'>
|
||||
0514fc90e6c7981b06bbb2173bb8ef03
|
||||
</query>
|
||||
</iq>
|
||||
<!-- Server -->
|
||||
<iq to='bill@shakespeare.lit/home' type='result' id='bill1'>
|
||||
<query xmlns='urn:xmpp:entityver:0' type='jabber:iq:roster'>
|
||||
0514fc90e6c7981b06bbb2173bb8ef03
|
||||
</query>
|
||||
</iq>
|
||||
]]></example>
|
||||
<p>
|
||||
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>
|
||||
<example caption="MUC rooms aggregate token request"><![CDATA[
|
||||
<!-- 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
|
||||
token IQ.
|
||||
</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>
|
||||
Clients are also NOT REQUIRED to check aggregate tokens. However, clients
|
||||
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
|
||||
tokens is left up to the clients.
|
||||
tokens (if at all) is left up to the implementation.
|
||||
</p>
|
||||
</section2>
|
||||
</section1>
|
||||
|
||||
<section1 topic='Implementation Notes' anchor='impl'>
|
||||
|
Loading…
Reference in New Issue
Block a user