The protocol sequence below is derived from an exchange between instances of my app. Typos could have crept in during editing!<br><br>There are features missing... splitting <revision/> messages to fit the max payload size for the node, and types for diff formats.<br>
<br>Feedback welcome!<br><br><br>1. Creator makes a pubsub node for incoming messages, and subscribes to it: (These nodes give us IQ for 1-to-1 messaging, even if recipient is offline.)<br><br><iq from='creator@localhost/<br>
reprev' to='pubsub.localhost'<br> type='set' id='9365' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br>
<create node='creator'/><br> <configure><x xmlns='jabber:x:data' type='submit'><br> <field var='FORM_TYPE' type='hidden'><value><a href="http://jabber.org/protocol/pubsub#node_config">http://jabber.org/protocol/pubsub#node_config</a></value></field><br>
<field var='pubsub#notify_retract'><value>0</value></field><br> <field var='pubsub#persist_items'><value>0</value></field><br> <field var='pubsub#publish_model'><value>open</value></field><br>
<field var='pubsub#access_model'><value>whitelist</value></field><br> <field var='pubsub#send_last_published_item'><value>never</value></field><br>
</x></configure></pubsub></iq><br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br> type='set' id='9366' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br>
<subscribe node='creator' jid='creator@localhost/reprev'/><br></pubsub></iq><br><br><br>2. Contributor does the same:<br><br><iq from='contributor@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='8776' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <create node='contributor'/><br>
<configure><x xmlns='jabber:x:data' type='submit'><br> <field var='FORM_TYPE' type='hidden'><value><a href="http://jabber.org/protocol/pubsub#node_config">http://jabber.org/protocol/pubsub#node_config</a></value></field><br>
<field var='pubsub#notify_retract'><value>0</value></field><br> <field var='pubsub#persist_items'><value>0</value></field><br> <field var='pubsub#publish_model'><value>open</value></field><br>
<field var='pubsub#access_model'><value>whitelist</value></field><br> <field var='pubsub#send_last_published_item'><value>never</value></field><br>
</x></configure></pubsub></iq><br><br><iq from='contributor@localhost/reprev' to='pubsub.localhost'<br> type='set' id='8777' xmlns='jabber:client'><br>
<pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <subscribe node='contributor' jid='contributor@localhost/reprev'/><br></pubsub></iq><br>
<br><br>3. Creator makes a pubsub node for a shared collection, and subscribes:<br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br> type='set' id='9367' xmlns='jabber:client'><br>
<pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <create node='uuid1.105'/><br> <configure><x xmlns='jabber:x:data' type='submit'><br>
<field var='FORM_TYPE' type='hidden'><value><a href="http://jabber.org/protocol/pubsub#node_config">http://jabber.org/protocol/pubsub#node_config</a></value></field><br> <field var='pubsub#notify_retract'><value>0</value></field><br>
<field var='pubsub#persist_items'><value>0</value></field><br> <field var='pubsub#publish_model'><value>subscribers</value></field><br> <field var='pubsub#access_model'><value>whitelist</value></field><br>
<field var='pubsub#send_last_published_item'><value>never</value></field><br></x></configure></pubsub></iq><br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='9368' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <subscribe node='uuid1.105' jid='creator@localhost/reprev'/><br>
</pubsub></iq><br><br><br>4. Creator revs the collection whitelist, notifies collection members of the whitelist change, and invites Contributor to join the collection:<br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='9372' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <affiliations node='uuid1.105'><br>
<affiliation jid='contributor@localhost' affiliation='publisher'/><br></affiliations></pubsub></iq><br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='9370' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <publish node='uuid1.105' jid='creator@localhost/reprev'><item><br>
<member xmlns='reprev_ns' uid="contributor@localhost" added="pending"><br> contributor@localhost<br></member></item></publish></pubsub></iq><br>
<br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br> type='set' id='9369' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br>
<publish node='contributor' jid='creator@localhost/reprev'><item><br> <invite xmlns='reprev_ns' collection="uuid1.105"><br> <from uid="creator@localhost">Liam</from><br>
<date>2010-01-19T20:45:26Z</date><br> <name>Cornucopia</name><br> <blurb>A non-descript invitation</blurb><br></invite></item></publish></pubsub></iq><br>
<br><br>5. Contributor subscribes to the collection, and notifies Creator:<br><br><iq from='contributor@localhost/reprev' to='pubsub.localhost'<br> type='set' id='8778' xmlns='jabber:client'><br>
<pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <subscribe node='uuid1.105' jid='contributor@localhost/reprev'/><br></pubsub></iq><br>
<br><iq from='contributor@localhost/reprev' to='pubsub.localhost'<br> type='set' id='8779' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br>
<publish node='creator' jid='contributor@localhost/reprev'><item><br> <join xmlns='reprev_ns' collection="uuid1.105" uid="contributor@localhost"/><br>
</item></publish></pubsub></iq><br><br><br>6. Creator replicates collection to Contributor, first meta/data and then revision history:<br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='9375' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <publish node='contributor' jid='creator@localhost/reprev'><item><br>
<replica xmlns='reprev_ns' collection='uuid1.105'><br> <!-- app-defined data --><br></replica></item></publish></pubsub></iq><br><br><iq from='creator@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='9376' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <publish node='contributor' jid='creator@localhost/reprev'><item><br>
<revision xmlns='reprev_ns' collection="uuid1.105"><br> <revlist touch="2010-01-19T20:52:34Z" oid="uuid1.118"><br> <object oid="uuid1.115" op="+" touch="2010-01-20T00:29:26Z" diff="uuid1.120"><br>
<object oid="uuid1.116" op="+" touch="2010-01-20T00:29:26Z" diff="uuid1.121"/></object></revlist><br> <diff orig="uuid1.115" oid="uuid1.120" type="not-implemented"><br>
<!-- app-defined content --></diff><br> <diff orig="uuid1.116" oid="uuid1.121" type="not-implemented"><br> <!-- app-defined content --></diff><br>
</revision></item></publish></pubsub></iq><br><br><br>7. Contributor makes a revision to collection:<br><br><iq from='contributor@localhost/reprev' to='pubsub.localhost'<br>
type='set' id='8784' xmlns='jabber:client'><br> <pubsub xmlns='<a href="http://jabber.org/protocol/pubsub">http://jabber.org/protocol/pubsub</a>'><br> <publish node='uuid1.105' jid='contributor@localhost/reprev'><item id='uuid2.106'><br>
<revision xmlns='reprev_ns' collection="uuid1.105"><br> <revlist touch="2010-01-19T21:00:36Z" oid="uuid2.106"><br> <object oid="uuid1.116" op="!" touch="2010-01-20T00:29:26Z" diff="uuid2.107"/></revlist><br>
<diff orig="uuid1.116" oid="uuid2.107" type="not-implemented"><br> <!-- app-defined content --></diff><br></revision></item></publish></pubsub></iq><br>
<br><br>8. Contributor resigns from collection:<br><br><!-- not yet implemented --><br><br><br><div class="gmail_quote">On Wed, Jan 20, 2010 at 3:44 PM, Liam <span dir="ltr"><<a href="mailto:pubsub@networkimprov.net">pubsub@networkimprov.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">I'm building an app which replicates collections of data objects among groups of contributors/subscribers.<br>
</div><div class="gmail_quote"><div class="im"><br>I use XMPP for transport & store-forward, and I've built a simple replication & revision system on top of PubSub.<br>
<br>I'm considering open sourcing this code and documenting the protocol. (Source is javascript requiring Strophe.) Creating a separate package for this would entail some work, so I'd like to gauge potential interest...<br>
<br>My replication & revision system does the following:<br><br>Establishes pubsub nodes for shared collections<br>Reliably transmits (reliable requires IQ Notifications):<br> - invitations to join a
collection<br> - invitation acceptances<br></div> - collection replicas to new members<br><div class="im"> - resignations from a collection<br> - revisions to a
collection, containing:<br> a) list of revised objects<br> b) diffs for added/modified objects<br> format is app-specific; common diff types may be specified<br><br></div>Obviously, it's very lightweight. It's not focused on real-time apps per se, but could be applied thereto.<br>
<div class="im">
<br>Also, I'd love pointers to other forums where folks could be interested...<br>
<br>Liam<br><br></div>PS: protocol specifics to follow...<br><br></div>
</blockquote></div><br>