From 61dd46602347ccf6433a4f1a958e7febd55532f0 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Mon, 7 Sep 2015 13:48:57 -0500 Subject: [PATCH] Add profiles / partial sync to entity versioning --- inbox/entityversioning.xml | 510 ++++++++++++++++++++++--------------- 1 file changed, 307 insertions(+), 203 deletions(-) diff --git a/inbox/entityversioning.xml b/inbox/entityversioning.xml index 5ac781ac..07b7097e 100644 --- a/inbox/entityversioning.xml +++ b/inbox/entityversioning.xml @@ -8,10 +8,9 @@
Entity Versioning - A method by which rosters and disco items may be versioned so that servers - will not need to send the entire list if it has not been modified, saving - bandwidth and time during session initialization with minimal state being - stored by the server and client. + A method by which lists of items may be versioned so that servers will not + need to send the entire list if it has not been modified, saving bandwidth + and time with minimal state being stored by the server and client. &LEGALNOTICE; xxxx @@ -37,6 +36,12 @@ Keen dkeen@atlassian.com + + 0.0.2 + 2015-09-17 + ssw +

Add profiles / parcial sync.

+
0.0.1 2015-08-25 @@ -48,17 +53,17 @@

This problem of "downloading the world" (downloading the entire roster - every time a session is initialized) was partially addressed by &xep0237; - which was later merged into &rfc6121; §2.6. While this solved the problem - for the roster, it didn't account for other entities (eg. disco items). + every time a session is initialized or receiving an entire disco items + response every time a MUC list is queried, etc.) was partially addressed by + &xep0237; which was later merged into &rfc6121; §2.6. While this solved + the problem for the roster, it didn't account for other entities. Furthermore, roster versioning requires that the server maintain a great deal of state (roster items which should be pushed for each entity on reconnect, or monotonically increasing counters, etc.) which can be difficult to store or synchronize in a large, distributed system. This XEP - defines a method by which the roster and entities other than the roster can - be versioned and cached, and which is optimized for distributed systems - with large enity lists (but works equally well on small, single server - deployments). + defines a method by which generic entity lists can be versioned and cached, + and which is optimized for distributed systems with large entity lists (but + works equally well on small, single server deployments).

@@ -96,8 +101,8 @@
Any abstract object which may be versioned (eg. rooms, users).
Version Token
- A generally short, case sensitive string which represents an entity and - changes if that entity changes. + A short, case sensitive string which represents an entity and changes if + that entity changes.
@@ -144,55 +149,103 @@ + +

+ Because entity versioning is designed to be a generic system for syncing + any sort of list in XMPP, and the format and requirements of various entity + lists may vary greatly, no specific wire format is defined in this + specification. Instead, the specifics for various lists will be left up to + separate XEPs which will define entity versioning "profiles" which must be + registered with the XMPP registrar. These profiles will define exactly how + version tokens are represented in the specific list format for which they + wish to use entity versioning. The rest of this document will provide + details about entity versioning which will be common to all entity + versioning profiles and do not need to be redefined in EV profile XEPs. It + will also define an EV profile for fetching the roster. +

+

+ The roster entity versioning profile which is used as an example throughout + this document will use the namespace 'urn:xmpp:entityver:profile:roster:0' + as described in the XMPP Registrar + Considerations section of this document. +

+
+ -

- If a server supports entity versioning, it MUST inform the connecting - client when returning stream features during the stream negotiation - process. This is done by including a <ver/> element, qualified by - the 'urn:xmpp:entityver:0' namespace. At the latest, this SHOULD - be done when informing a client that resource binding is required. For - example: -

- + If a server supports entity versioning, it MUST inform the connecting + client when returning stream features during the stream negotiation + process. This is done by including a <ver/> element, qualified by the + 'urn:xmpp:entityver:0' namespace with child <profile> nodes for each + supported entity versioning profile. At the latest, this SHOULD be done + when informing a client that resource binding is required. For example if + the server only supports versioning of rosters it might return: +

+ - + + + - ]]> + ]]>

The entity versioning stream feature is merely informative and therefore is never mandatory-to-negotiate.

+

+ Clients, servers, and other entities that support &xep0030; and entity + versioning must respond to service discovery requests with a feature of + 'urn:xmpp:entityver:0' and with a feature for each EV profile supported by + the responding entity as described in the relavant specifications. Eg. a + response from a server that supports roster versioning for the requesting + entity might look like the following: + + + + + + + ]]> +

- -

- 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. -

-

- 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. -

-

For example, a roster request might look like:

- + +

+ 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. +

+

+ Servers that implement this protocol must assign such a version token to + each entity that is controlled by the server. The server SHOULD 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. +

+

+ For example, a versioned roster request might look like this: + @@ -213,64 +266,25 @@ - ]]> + ]]> +

Note that in this case there may be three roster items total (and the client only knows about two of them), or there may be two total roster items and the server is informing the client about a change to "bill@shakespeare.lit". Version tokens MUST also be present in roster pushes: -

- + - - - XWE4MUUP - - - - ]]> -

A disco request for rooms (as defined in &xep0045;) might look like:

- - - - 25P2A7H8 - - - 4OLGSVNY + + + XWE4MUUP - - - - - - VIZSVF0D - - - - ]]> -

- In this example coven@chat.shakespeare.lit has been modified (eg. the - room name might have been changed), but inverness@chat.shakespeare.lit - has not changed, therefore no update is sent down. -

-

- Clients that implement this protocol SHOULD then cache the entity in - question when a version token is received. -

- + ]]>
+

+

When a client syncs with the server and indicates that it has a version @@ -278,127 +292,154 @@ 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: - - - - - 25P2A7H8 - - - 4OLGSVNY - - - - - - - - - - - - - ]]> + from its cache. For example, the following would remove the roster item + 'bill@shakespeare.lit' from the cache: + + + + + + + + ]]>

- 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. + Roster pushes that indicate a deleted item MUST also remove the version + from the cache (and need not contain an empty <version/> element).

-
- -

- 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 - more information to be sent by the client when requesting a list of - entities. For a very large list which is not likely to have changed, it may - be useful know in advance if the roster has changed or not (so that we can - 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 "JID:version" pairs sorted 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: -

- +

+ For very large groups fetching an entire list may not be practical or + necessary. For example, one might imagine a large corporation with a + shared roster that is too large for its version tokens to be sent up to + the server on every sync, or even to download fully the first time. To + solve this, servers MAY choose to send down only a part of an entity list + in response to a query (unless the individual EV profile forbids partial + list sync). How servers choose what items to return is an implementation + detail that is out of the scope of this document. Some suggestions may be + found in the Implementation Notes. On subsequent + requests for the entity list, the server MAY choose to return more + entities (eg. based on changes in its internal selection criteria), + however it MUST NOT invalidate cached entities unless they have actually + been removed from the list. +

+

+ XEPs defining entity versioning profiles MUST include a section to + indicate if partial sync is supported, and if so, how it will be + indicated to the client (and how the client can request a full list). If + no mechanism is specified, this is done by adding a boolean "full_list" + attribute to the request, eg. a roster request for a partial list looks + like: + + + + + 25P2A7H8 + + + VIZSVF0D + + + + + + + + 9ZFZXVP9 + + + + ]]> +

+

+ When making a request for a partial list, clients do not need to send up + every entity in their cache. Instead they MAY send up just those entities + for which they wish to check for updates. The server MUST then respond + with any updates for those entities, and MAY also add other entities to + the list if desired. If the client requests a partial list but does not + indicate that it has anything in its cache, what entities to return (if + any) is left up to the server implementation. +

+ + +

+ 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 + more information to be sent by the client when requesting a list of + entities. For a very large list which is not likely to have changed, it + may be useful know in advance if the roster has changed or not (so that + we can 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 "ID:version" + pairs sorted in byte-wise order (because the ID:version pair is + constructed before sorting, if two items in the list have the same ID + they can still be sorted by the version token), and taking the MD5 hash + of the constructed string. The ID in the pair is any ID or key that + identifies the entity as defined in its profile (eg. a JID for roster + items and most other entities). For example, if the server is calculating + the aggregate version token for a roster, it might end up with the + following string: +

+ -

- Which results in the aggregate token: -

- +

+ Which results in the aggregate token: +

+ -

- 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 with the type set to the `jabber:iq:roster` - namespace: -

- +

+ 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 with the query's XMLNS set to + 'urn:xmpp:entityver:profile:roster:0': +

+ - + - + 0514fc90e6c7981b06bbb2173bb8ef03 - ]]> -

- Similarly, to fetch the aggregate token for a list of MUC rooms, one would - query the MUC component directly with the type set to the 'disco#items' - namespace: -

- - - - - - - - - 32151d1d01440d5536a7f106afd3f4d8 - - - ]]> -

- Because aggregate tokens are OPTIONAL to implement, clients MUST fall back - to a normal request if any error is returned in response to an aggregate - token IQ. -

-

- 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). -

-

- 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 (if at all) is left up to the implementation. -

+ ]]>
+

+ Because aggregate tokens are OPTIONAL to implement, clients MUST fall + back to making a normal list request if any error is returned in response + to an aggregate token IQ. +

+

+ 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). +

+

+ Because aggregate tokens are calculated for the entire list as seen by + the client or server, they will never match if partial lists have been + downloaded by the client. +

+

+ 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 (if at all) is left up to the implementation. +

+
-

Version tokens may not provide enough collision resistance across versioned @@ -421,6 +462,22 @@ anne@shakespeare.lit:VIZSVF0D,bill@shakespeare.lit:25P2A7H8 version token MAY be used as a weakly validated ETag for any API requests for that entity.

+

+ Servers following this specification may choose to send down partial entity + lists in response to queries. For the case of rosters one or more of the + following may be returned to the requesting entity during the initial + roster sync: +

    +
  • + Users that are grouped with the requester in some way. Eg. for a + company with a large shared roster which places the requesting client + in the "Marketing Department" group, the server may wish to return + roster items that also share that group. +
  • +
  • Users whom the requester has contacted recently or frequently.
  • +
  • Users that should always be returned as part of server policy.
  • +
+

@@ -449,6 +506,53 @@ anne@shakespeare.lit:VIZSVF0D,bill@shakespeare.lit:25P2A7H8 &xep0053;.

+ + &NSVER; + + +

+ The XMPP Registrar shall maintain a registry of entity versioning + profiles. All EV profile registrations shall be defined in separate + specifications (not in this document). Application types defined within + the XEP series MUST be registered with the XMPP Registrar, resulting in + protocol URNs of the form "urn:xmpp:entityver:profile:name:X" (where + "name" is the registered name of the profile and "X" is a non-negative + integer). +

+ ®PROCESS; + + The name of the entity versioning profile. + A natural-language summary of the profile. + + The document in which the original list definition is specified. + + + The document in which the EV profile for the list is specified (may be the + same as <listdev/>). + + + ]]> +
+ +

This specification defines the following entity versioning profile:

+
    +
  • urn:xmpp:entityver:profile:roster:0
  • +
+

+ Upon advancement of this specification from a status of Experimental to a + status of Draft, the ®ISTRAR; shall add the following definition to + the entity versioning profiles registry, as described in this document: + + Roster entity versioning + Allows versioning of entities in an XMPP roster. + RFC 6121 + TODO: Insert this document once it is assigned a number + + ]]> +

+