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:
parent
f7eb0a8a8c
commit
8c40f32172
@ -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 <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[
|
<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 <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'
|
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'>
|
||||||
|
Loading…
Reference in New Issue
Block a user