<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">

<channel>
	<title>Collaboration: Theory and Practice</title>
	<atom:link href="http://wave.thewe.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://wave.thewe.net</link>
	<description>Developing powerful foundations for adaptable information-centric applications with Google Wave</description>
	<lastBuildDate>Fri, 12 Feb 2010 07:28:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>What we&#8217;ve been working on&#8230;</title>
		<link>http://wave.thewe.net/2010/02/05/what-weve-been-working-on/</link>
		<comments>http://wave.thewe.net/2010/02/05/what-weve-been-working-on/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 16:53:15 +0000</pubDate>
		<dc:creator>Avital Oliver</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=177</guid>
		<description><![CDATA[So much has happened since we started this project. We didn&#8217;t really know what we&#8217;d end up doing &#8211; we just had a vision and a bunch of ideas. At this point we realized how naive our approach was &#8211; we needed foundations much deeper in order to achieve our vision.
Anyways, here is a short video [...]]]></description>
			<content:encoded><![CDATA[<p>So much has happened since we started this project. We didn&#8217;t really know what we&#8217;d end up doing &#8211; we just had a vision and a bunch of ideas. At this point we realized how naive our approach was &#8211; we needed foundations much deeper in order to achieve our vision.</p>
<p>Anyways, here is a short video about what we&#8217;ve been doing. Enjoy.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="300" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=9231418&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="300" src="http://vimeo.com/moogaloop.swf?clip_id=9231418&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2010/02/05/what-weve-been-working-on/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Logging and Debugging in Clojure &#8211; Followup (Complete Tracing)</title>
		<link>http://wave.thewe.net/2009/12/17/logging-and-debugging-in-clojure-followup-complete-tracing/</link>
		<comments>http://wave.thewe.net/2009/12/17/logging-and-debugging-in-clojure-followup-complete-tracing/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 12:39:57 +0000</pubDate>
		<dc:creator>Ayal Gelles</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=155</guid>
		<description><![CDATA[
Following some interesting comments on our previous blog post we thought it would be appropriate to emphasize the added value of our logging approach (which we now realize we should call &#8220;complete tracing&#8221;) compared to the others mentioned. To demonstrate, let&#8217;s observe some simple code for manipulating sets. As background, a partition is defined to [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>Following some interesting comments on <a href="http://wave.thewe.net/2009/11/22/logging-and-debugging-in-clojure/">our previous blog post</a> we thought it would be appropriate to emphasize the added value of our logging approach (which we now realize we should call &#8220;complete tracing&#8221;) compared to the others mentioned. To demonstrate, let&#8217;s observe some simple code for manipulating sets. As background, a partition is defined to be a set of mutually disjoint sets. Each of the sets in a partition is usually called a class. For example: If this is the partition #{#{1 2} #{3 4 5}} then #{1 2} is a class. What makes this a partition is that no two classes share a member.</p>
<p>Now, consider the following functions that carry out the task of &#8220;linking&#8221; two simple elements (the ones that belong to the classes which are inside the partition) to a given partition:</p>
<pre style="line-height: 100%;">(defn add-to-class [partition class el]
  (conj (disj partition class) (conj class el)))

(defn containing-class [partition el]
  (first (for [class partition :when (some #{el} class)] class)))

(defn link-elements-in-partition [partition el1 el2]
  (let [c1 (containing-class partition el1)
        c2 (containing-class partition el2)]
    (cond

      (and (not c1) (not c2)) ; neither are in any class (we add it to c1)
      (conj partition #{el1 el2})

      (and c1 (not c2)) ; el1 was found in a class (c1) while el2 was not (we add it to c2)
      (add-to-class partition c1 el2)

      (and c2 (not c1)) ; el2 was found in a class (c2) while el1 was not
      (add-to-class partition c2 el1)

      (and (and c1 c2) (not= c2 c2)) ; both were found in different classes (we join them)
      (conj (disj partition c1 c2) (union c1 c2))

      :else
      partition)))</pre>
<p>For example, (link-elements-in-partition #{#{1 2} #{3} #{4 5}} 2 3) should return #{#{1 2 3} #{4 5}}) and (link-elements-in-partition #{#{1 2} #{3 4 5}} 3 2) should return #{1 2 3 4 5}. Yet if you try to run this code it returns #{#{1 2} #{3 4 5}}. There is a bug.</p>
<p>Let us examine the output of the clojure-contrib trace library (after re-defining the functions with &#8220;deftrace&#8221;) and see if it can help us find the source of the problem.</p>
<pre style="line-height: 100%;">TRACE t32800: (link-elements-in-partition #{#{1 2} #{3 4 5}} 3 2)
TRACE t32801: | (containing-class #{#{1 2} #{3 4 5}} 3)
TRACE t32801: | =&gt; #{3 4 5}
TRACE t32802: | (containing-class #{#{1 2} #{3 4 5}} 2)
TRACE t32802: | =&gt; #{1 2}
TRACE t32800: =&gt; #{#{1 2} #{3 4 5}}</pre>
<div>Hmmm&#8230; not much information to work with. The problem must be somewhere in the big &#8220;cond&#8221; clause and the &#8220;trace&#8221; just doesn&#8217;t dig in to it.</div>
<div>This is where code walking comes in handy. By merely using defn-ctrace instead of deftrace you get our complete internal tracing functionality. Then, run the following code:</div>
</div>
<pre style="line-height: 100%;">(start-complete-tracing)
(link-elements-in-partition #{#{1 2} #{3 4 5}} 3 2)
(end-complete-tracing-and-print-org-mode)</pre>
<div>That last function prints a string value that represents the trace tree, the format of this string is designed for use with emacs&#8217; <a href="http://orgmode.org/" target="_blank">org-mode</a>, which gives really great subtree expand/collapse capabilities. Here is the full result: <a href="http://gist.github.com/260408" target="_blank">http://gist.github.com/260408</a></div>
<div>
<p>Just to quickly see how it would have helped us solve the issue, here is a snippet of the complete tracing result (from within the cond expression), with lines slightly re-ordered to give a similar effect to using org-mode.</p>
<pre style="line-height: 100%;">**** (and (and c1 c2) (not= c2 c2))
**** `=&gt; Result:
false
***** (and c1 c2)
***** `=&gt; Result:
#{1 2}
****** c1
****** `=&gt; Result:
#{3 4 5}
****** c2
****** `=&gt; Result:
#{1 2}
***** (not= c2 c2)
***** `=&gt; Result:
false
****** c2
****** `=&gt; Result:
#{1 2}
****** c2
****** `=&gt; Result:
#{1 2}</pre>
<p>It is obvious that the top condition in this subtree should have evaluated &#8220;true&#8221; &#8211; and it is also obvious that the reason it fails to do so is the (not= c2 c2) part of it. Tracing even into <em>that</em> expression leaves no room for doubt &#8211; it was a typo, it should have been (not= c1 c2).</p>
<p>This library has already saved us days of debugging time and we are continuing to develop it &#8211; fixing bugs, adding support for more forms (you&#8217;d want to see a different form of tracing for if, do, cond, and, etc), writing some emacs utils and cleaning up the code. If you want to dive into some alpha stage code, feel free to take a look at  <a href="http://github.com/theWE/thewe/blob/master/robot/ctrace.clj" target="_blank">http://github.com/theWE/thewe/blob/master/robot/ctrace.clj</a>. We will continue to polish this project in the upcoming period of time and plan to properly package it and release it at the proper time.<span><br />
</span></div>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/12/17/logging-and-debugging-in-clojure-followup-complete-tracing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Logging and Debugging in Clojure, or How Macros and Functional Programming Saved the Day (again) [part 1]</title>
		<link>http://wave.thewe.net/2009/11/22/logging-and-debugging-in-clojure/</link>
		<comments>http://wave.thewe.net/2009/11/22/logging-and-debugging-in-clojure/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 10:52:52 +0000</pubDate>
		<dc:creator>Ayal Gelles</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.thewe.net/?p=140</guid>
		<description><![CDATA[This post has a follow-up.

&#8220;I object to doing things that computers can do&#8221; &#8212; Olin Shivers
We are all familiar with the following scenario &#8211; You write some code. Everything is working. You change your code just a little bit&#8230;
Incidental logging and step-by-step debugging are basically the same thing. You make your way through your code [...]]]></description>
			<content:encoded><![CDATA[<p>This post has a <a href="http://wave.thewe.net/2009/12/17/logging-and-debugging-in-clojure-followup-complete-tracing/" target="_blank">follow-up</a>.</p>
<hr />
<em>&#8220;I object to doing things that computers can do&#8221; &#8212; Olin Shivers</em></p>
<p>We are all familiar with the following scenario &#8211; You write some code. Everything is working. You change your code <em>just a little bit&#8230;</em></p>
<p>Incidental logging and step-by-step debugging are basically the same thing. You make your way through your code in a divide-and-conquer search for the cause of an unexpected result. You add a log here, you debug a function there, you step-into-outta-over-and-out. And then you finally find it &#8211; the function that returns the wrong value. And then, hopefully, the line that messes everything up. It took you almost forever and you know that with the next bug everything will happen all over again. But you always have a feeling that there is some reason guiding you through this weird process. And it&#8217;s true &#8211; Logging is clearly a job for a computer. So we asked ourselves &#8211; why not automatically log all arguments and return-values for any function call?</p>
<p>If you were to try implementing this in other languages you would find out you need to pursue one of two approaches, both fundamentally flawed. One would be to preprocess your code and inject logs. Another approach would be to implement some hideous reflection mechanism to inject the logs in the right places. The first approach would require heavy coding and either text-parsing or some use of a code analysis library, the second approach would require compiling code at runtime. Luckily for us, a preprocessed code-walking in Lisp is as simple as writing a function that iterates a list. Well, It is iterating a list!. Moreover, what would be the right places to inject logs at? Well, if you write in functional style, you really know for certain that you only need to log the arguments and return value of every function (or a sub-special-form of a function). In a non-functional programming language (any language that allows modifying variables) this certainty doesn&#8217;t exist. Therefore, any attempt to automatically generate all needed logs would require the logging of all variables after each and every single line of code.</p>
<p>In Lisp, a code-walker macro can be written that will iterate a function&#8217;s s-expression and &#8220;inject&#8221; log calls before every sub-expression call. We had some issues with handling Clojure&#8217;s special forms like &#8220;let&#8221; and &#8220;for&#8221;, but victory was eventually ours. It ended up looking like <a href="http://github.com/avital/thewe-clojure-relay/blob/master/clj/debug.clj" target="_blank">this</a>.</p>
<p>The question still arises: How will we view such a monstrous amount of logs? We would really want to be able to view it as if its a simulation of the actual run of the program. So we wrote a small Javascript application to display the results of the logging in such a way. And that looks something like this:</p>
<p><img class="alignnone size-full wp-image-147" title="Sample Debug Tree" src="http://blog.thewe.net/wp-content/uploads/2009/11/json-tree3.png" alt="json-tree" width="480" height="410" /></p>
<p>With that said, we are aware that as our project will grow in complexity it may not be feasible to continue with this paradigm. However, thanks to Clojure, we believe that we will be able to find ways to maintain some parts of it by improving the logging mechanism to be less verbose and more precise.</p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/11/22/logging-and-debugging-in-clojure/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Developing Google Wave Robots Outside of Google App Engine with Clojure</title>
		<link>http://wave.thewe.net/2009/10/19/developing-google-wave-robots-outside-of-google-app-engine-with-clojure/</link>
		<comments>http://wave.thewe.net/2009/10/19/developing-google-wave-robots-outside-of-google-app-engine-with-clojure/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 11:56:16 +0000</pubDate>
		<dc:creator>Ayal Gelles</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=131</guid>
		<description><![CDATA[Lately we are very interested in Lisp and the immense productivity gain when developing with it, and we are especially enthusiastic about Clojure, a new dialect of Lisp. Therefore we thought of trying to write some Wave robots in Clojure.
Some people have already experimented with writing robots in Clojure (for example here and here). However, [...]]]></description>
			<content:encoded><![CDATA[<p>Lately we are very interested in Lisp and the immense productivity gain when developing with it, and we are especially enthusiastic about <a title="Clojure" href="http://clojure.org/" target="_blank">Clojure</a>, a new dialect of Lisp. Therefore we thought of trying to write some Wave robots in Clojure.</p>
<p>Some people have already experimented with writing robots in Clojure (for example <a href="http://spanx.wordpress.com/2009/07/23/clojure-robot-on-google-wave/" target="_blank">here</a> and <a href="http://www.fatvat.co.uk/2009/07/google-wave-and-clojure.html" target="_blank">here</a>). However, these approaches still assume that development is done on Google App Engine (GAE). This means that you have to redeploy each time there is a new version of your robot (contrary to the common Lisp way which is just evaluating code into a remote process, known as a REPL). We also wanted to use an in-memory database instead of dealing with database schemas and other irrelevant issues for prototyping. This can&#8217;t be done with GAE since each robot event gets sent to a different machine running the robot code and the memory is not shared.</p>
<p>In order to write in Clojure and use an in-memory database, we had to find a way to write our code outside of GAE. Google currently allows robots to only be run on GAE so the solution was writing a relay robot to manage the communication between the Wave server to our Clojure server. More technically, our relay robot is written in Java and all it does is intercept the JSON objects coming in from the Wave server, post them to a web server running <a href="http://github.com/weavejester/compojure" target="_blank">Compojure</a> (a Clojure web server), wait for a response (the JSON object describing the operations to be done on the wave) and pass it back to be processed.</p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/10/19/developing-google-wave-robots-outside-of-google-app-engine-with-clojure/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google Wave Gadgets using MooTools</title>
		<link>http://wave.thewe.net/2009/09/07/google-wave-gadgets-using-mootools/</link>
		<comments>http://wave.thewe.net/2009/09/07/google-wave-gadgets-using-mootools/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 16:44:13 +0000</pubDate>
		<dc:creator>Avital Oliver</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=112</guid>
		<description><![CDATA[We have been using MooTools to develop our gadgets and that wasn&#8217;t causing any problems on top of our emulator. But apparently our gadgets weren&#8217;t working on the real Wave sandbox. After a lot of debugging it turned out that Wave&#8217;s JSON object conflicts with MooTools&#8217; own JSON object. In order to use develop Wave [...]]]></description>
			<content:encoded><![CDATA[<p>We have been using MooTools to develop our gadgets and that wasn&#8217;t causing any problems on top of our emulator. But apparently our gadgets weren&#8217;t working on the real Wave sandbox. After a lot of debugging it turned out that Wave&#8217;s JSON object conflicts with MooTools&#8217; own JSON object. In order to use develop Wave gadgets using MooTools, use the <a href="http://mootools.net/core">MooTools Core Builder</a> and remove the JSON component. </p>
<p>If you still want to encode and decode JSON, you can use Wave&#8217;s HTML 5-compliant JSON functions (JSON.stringify and JSON.parse instead of MooTools&#8217; JSON.encode and JSON.decode).</p>
<p><strong>Update:</strong> Rasmus Fløe brought up a much simpler solution which allows you to still use MooTools&#8217; JSON API. Instead of ommitting MooTools JSON from Core, just extend the JSON object: $extend(JSON, {stringify: JSON.encode, parse: JSON.decode});</p>
<p>Here&#8217;s the <a href="http://wave.thewe.net/gadgets/todo/todo.xml">source code</a> for task list gadget and the <a href="http://wave.thewe.net/2009/06/15/concurrency-in-gadget-state/">original blog post</a> about it.</p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/09/07/google-wave-gadgets-using-mootools/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating a reorderable task list &#8211; Managing gadget states with concurrency in mind</title>
		<link>http://wave.thewe.net/2009/06/15/concurrency-in-gadget-state/</link>
		<comments>http://wave.thewe.net/2009/06/15/concurrency-in-gadget-state/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 17:01:48 +0000</pubDate>
		<dc:creator>Avital Oliver</dc:creator>
				<category><![CDATA[Essay]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=56</guid>
		<description><![CDATA[My first attempt at creating a wave gadget is a reorderable task list. Here is an embedded version of the gadget running in the emulator. 



As I started the implementation, I realized that there are certain difficulties with gadget state management with regard to Wave&#8217;s real-time concurrency. Here is an attempt to recreate the learning [...]]]></description>
			<content:encoded><![CDATA[<p>My first attempt at creating a wave gadget is a reorderable task list. Here is an embedded version of the gadget running in the emulator. </p>
<p style="padding-left: 30px;">
<p><iframe width="100%" height="360" frameborder="0" id="gadgetframe" src="/emulator/simple.html#http://wave.thewe.net/gadgets/todo/todo.xml!756105800" style="overflow: hidden; display: block;" name="gadgetframe"></iframe></p>
<p style="padding-left: 30px;">
<p>As I started the implementation, I realized that there are certain difficulties with gadget state management with regard to Wave&#8217;s real-time concurrency. Here is an attempt to recreate the learning process I went through, with the difficulties I encountered and solutions I put in place to make this gadget work.</p>
<ul>
<li>This is just a preliminary version of the gadget &#8211; I am still tweaking the user interaction so that concurrency is completely flawless.</li>
<li>I do not have access to the real Wave sandbox. All my development is done using the <a href="http://wave.thewe.net/emulator" target="_blank">gadget emulator</a>. As far as I know, this does <strong>not</strong> work on the real Wave server (but it&#8217;s probably a small fix if I could debug it)</li>
<li>This is long and technical. Think of it as a guided discussion.</li>
</ul>
<p><span id="more-56"></span></p>
<h2>Background</h2>
<p>Gadget states consist of a set of key-value pairs (like a hash table, associative array or Javascript object). It is important to note that as opposed to Javascript objects, gadget state values <strong>are always strings</strong> (and not arrays or other objects). If you want to see what some gadget states look like, try the <a href="http://wave.thewe.net/emulator" target="_blank">gadget emulator</a> &#8211; it shows the gadget state besides the gadget itself. If you take a look around, you will see a whole assortment of hacks to manage gadget state even though it only allows strings as values. When I asked in the google group about this, I was suggested to JSON encode any objects or arrays I want to store and use that string as the value in the state.</p>
<p>JSON encoding objects and arrays into strings is a hack, but that&#8217;s not the real problem. The issue is how that works with the way gadgets modify their state. In the <a href="http://code.google.com/apis/wave/extensions/gadgets/reference.html" target="_blank">gadget API reference</a> you will find that gadgets modify their state by submitting a delta. A delta is just another set of key-value pairs that state which keys to modify, and which new value to give them. If a null value is submitted then that key is removed from the gadget state.</p>
<h2>Approach #1</h2>
<p>Let&#8217;s start by trying to implement a simple task list without reorderability. We have to think of our gadget state scheme. How about using the idea to store the array of tasks by JSON encoding it? Then the state will look something like this:</p>
<p style="padding-left: 30px;"><strong>tasks:</strong> &#8220;['Go to store', 'Clean home', 'Finish blog post']&#8220;</p>
<p>Seems simple enough. Let&#8217;s imagine two people working on the same gadget instance and trying to add a new task at the same time. Participant #1 submits the following delta:</p>
<p style="padding-left: 30px;"><strong>tasks: </strong>&#8220;['Go to store', 'Clean home', 'Finish blog post', 'Go to sleep']&#8220;</p>
<p>while participant #2 submits:</p>
<p style="padding-left: 30px;"><strong>tasks: </strong>&#8220;['Go to store', 'Clean home', 'Finish blog post', 'Check xkcd']&#8220;</p>
<p>In effect, the Wave server will receive one of the deltas followed by the other, which means the end result will be whichever delta was applied by the server last. One of the new tasks will <strong>necessarily</strong> not appear (although it will be visible in the gadget history right before it got erased). And actually, <strong>no concurrent modifications will ever work</strong> with this scheme.  Can we find a different approach that will not have this problem?</p>
<h2>Approach #2</h2>
<p>We can try to put the different tasks in separate keys of the state, for example:</p>
<p style="padding-left: 30px;"><strong>task_1: </strong>&#8216;Go to store&#8217;<br />
<strong>task_2: </strong>&#8216;Clean home&#8217;<br />
<strong>task_3: </strong>&#8216;Finish blog post&#8217;</p>
<p>This approach will allow modification of specific tasks to work in a concurrent fashion, but adding a new task will have the same problem as approach #1.</p>
<h2>Approach #3</h2>
<p>The problem with approach #2 is that two participants will try to modify the same key when they each add a new task. If we want to solve this, we need to make sure that the key sent by both participants is different. Each participant has a unique participant id which is accessible from the gadget API. Let&#8217;s augment the keys with the participant id who added them. So, the initial state will look something like this (assuming the two participant id&#8217;s are 722931 and 199882):</p>
<p style="padding-left: 30px;"><strong>task_1_722931: </strong>&#8216;Go to store&#8217;<br />
<strong>task_2_199882: </strong>&#8216;Clean home&#8217;<br />
<strong>task_3_722931: </strong>&#8216;Finish blog post&#8217;</p>
<p>Now, the two deltas being submitted for the addition of the fourth task would be:</p>
<p style="padding-left: 30px;"><strong>task_4_722931:</strong> &#8216;Go to sleep&#8217;</p>
<p>and</p>
<p style="padding-left: 30px;"><strong>task_4_199882:</strong> &#8216;Check xkcd&#8217;</p>
<p>Which means the gadget state after both deltas were submitted would be:</p>
<p style="padding-left: 30px;"><strong>task_1_722931: </strong>&#8216;Go to store&#8217;<br />
<strong>task_2_199882: </strong>&#8216;Clean home&#8217;<br />
<strong>task_3_722931: </strong>&#8216;Finish blog post&#8217;<br />
<strong>task_4_722931:</strong> &#8216;Go to sleep&#8217;<br />
<strong>task_4_199882:</strong> &#8216;Check xkcd&#8217;</p>
<p>That has the slight weirdness of having two task_4_* keys but there&#8217;s no need for the UI to expose that in any way, so concurrent modifications worked as far as the user is concerned (which is the only thing that really matters).</p>
<p>But, actually, there is a problem with this approach &#8211; it would fail if the same user is trying to modify the gadget from two different computers. But that can be easily amended, by using a randomly generated code instead of the participant id. If we use, let&#8217;s say, 96 possible characters with a code length of 6 characters, we can reach over 700 million options for each code. That basically means you&#8217;ll never have any concurrency problems. And if you did, it will probably never happen again to you (remember, this could only even perhaps cause an issue if two people are adding a new task at the same time anyways.)</p>
<h2>Approach #4</h2>
<p>Let&#8217;s take on reorderability now. If we take the gadget state after the two new tasks were added, now we want to move &#8216;Finish blog post&#8217; to come right before &#8216;Clean home&#8217;. What delta would have to be submitted? The following delta seems like it may work:</p>
<p style="padding-left: 30px;"><strong>task_2_199882: </strong>&#8216;Finish blog post&#8217;<br />
<strong>task_3_722931: </strong>&#8216;Clean home&#8217;</p>
<p>Let&#8217;s see what happens if we would use this scheme and another user tries to move &#8216;Clean home&#8217; to come before &#8216;Go to store&#8217; with the following delta:</p>
<p style="padding-left: 30px;"><strong>task_1_722931: </strong>&#8216;Clean home&#8217;<br />
<strong>task_2_199882: </strong>&#8216;Go to store&#8217;</p>
<p>If the two deltas are submitted at once and the first gets applied before the second, we get the following gadget state:</p>
<p style="padding-left: 30px;"><strong>task_1_722931: </strong>&#8216;Clean home&#8217;<br />
<strong>task_2_199882: </strong>&#8216;Finish blog post&#8217;<br />
<strong>task_3_722931: </strong>&#8216;Clean home&#8217;<br />
<strong>task_4_722931:</strong> &#8216;Go to sleep&#8217;<br />
<strong>task_4_199882:</strong> &#8216;Check xkcd&#8217;</p>
<p>Oh no! Clean home appears twice and Go to store disappeared!</p>
<p>If you are following this discussion and you find it interesting, now is probably a good time to stop reading, grab a piece of paper and a pen (or a chalkboard if you have one around) and  try to find a solution for these concurrent reordering issues. Take into account that the scheme should also allow for modification or removal of a task at the same time as it is being moved around. Also, how would we be able to move &#8216;Finish blog post&#8217; to go between &#8216;Go to sleep&#8217; and &#8216;Check xkcd&#8217;? They are both &#8220;task_4&#8243;!</p>
<h2>Solution</h2>
<p>Let me start by saying that this is the solution I came up with and the paradigm used in <a href="http://wave.thewe.net/emulator/#http://wave.thewe.net/gadgets/todo/todo.xml!955255904" target="_blank">my implementation</a>. If you think of other possible solutions, I&#8217;d love to hear about them. They may be better than mine.</p>
<p>The main observation is that since any two deltas may interfere with each other if they touch the same attributes, we must ensure that the attributes modified properly represent the action taken by the user. For example, the last example of a possible delta to represent moving &#8216;Clean home&#8217; to come before &#8216;Go to store&#8217; contains two attributes, even though the user only acted on &#8216;Clean home&#8217;. It&#8217;s good to try to put it in words. The delta submitted means &#8220;Put &#8216;Clean home&#8217; at position 1 and &#8216;Go to store&#8217; at position 2&#8243; when our scheme should allow for a delta that means &#8220;Put &#8216;Clean home&#8217; before &#8216;Go to store&#8217;&#8221;. Also, if possible we should be able to allow for one user to modify the text on a task at the same time as it is being moved. That means that we must ensure that attributes in a delta modifying the position of a task do not conflict with the attributes in a delta modifying the text of a task. And in general, it is a good idea to be able to represent user actions as modifying one attribute only. This gives the best chance that concurrent modifications won&#8217;t conflict.</p>
<p>The solution has two attributes for each task &#8211; one for the text and one for the position. Each task would have to get a random id generated. Here is a sample gadget state in our scheme (remember that only strings are allowed as values):</p>
<p style="padding-left: 30px;"><strong>task_826721_text: </strong>&#8216;Go to store&#8217;<br />
<strong>task_826721_position: </strong>&#8216;1&#8242;<br />
<strong>task_612229_text: </strong>&#8216;Clean home&#8217;<br />
<strong>task_612229_position: </strong>&#8216;2&#8242;<br />
<strong>task_172034_text: </strong>&#8216;Finish blog post&#8217;<br />
<strong>task_172034_position: </strong>&#8216;3&#8242;</p>
<p>Modifying the text of a task would submit a delta only modifying the _text attribute. In order to move &#8216;Clean home&#8217; to come before &#8216;Go to store&#8217; we submit the following delta:</p>
<p style="padding-left: 30px;"><strong>task_612229_position: </strong>&#8216;0&#8242;</p>
<p>In order to move &#8216;Go to store&#8217; to come after &#8216;Clean home&#8217; (which may seem like the same operation but is not &#8211; think what would happen if someone else moves &#8216;Finish blog post&#8217; at the same time) we submit the following delta:</p>
<p style="padding-left: 30px;"><strong>task_826721_position: </strong>&#8216;2.5&#8242;</p>
<p>This means that positions must now be floating point numbers. Try to apply those two deltas and see what gadget state we reach. Think what would happen if someone else moves &#8216;Finish blog post&#8217; at the same time.</p>
<p>There are just two minor issues. First of all, two people might move two different items to position 2.5. This on its own is not necessarily an issue but then one wouldn&#8217;t be able to put something between those two positions (it would also need to be position 2.5 but then there is no way to ensure that it is between the two). In order to solve this, instead of using the average of the two positions you are placing between we use a random number in that range (with a certain predefined precision.) Secondly, Floating point numbers have bounded precision, which means that at some point if a list is reordered a lot, the scheme will stop working. In order to solve this, we used a library for arbitrary precision floating point numbers, which are encoded in base-64.</p>
<h2>Epilogue</h2>
<p>Thank you for joining us for this lengthy exploration. Please let me know what you think of this form of presentation, as it is my first attempt of this kind. As for the gadget state paradigm, I realize that this is way too difficult to be implemented for each gadget separately, and I would like for gadgets to work with perfect concurrency. Therefore, once I have some more free time, I&#8217;ll start working on a framework that hides all these technicalities from the gadget developer. </p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/06/15/concurrency-in-gadget-state/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Robot/Gadget Combo &#8211; Participant Map</title>
		<link>http://wave.thewe.net/2009/06/11/robotgadget-combo-participant-map/</link>
		<comments>http://wave.thewe.net/2009/06/11/robotgadget-combo-participant-map/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 17:39:09 +0000</pubDate>
		<dc:creator>Avital Oliver</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=42</guid>
		<description><![CDATA[Brian Flood has just published a robot/gadget combo that displays a map showing the locations of the wave participants using several different geolocation API&#8217;s and Google Maps. Here&#8217;s some information about robots and gadgets. I don&#8217;t have sandbox access so I can&#8217;t test it but here are some preliminary comments.

This is the first time I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Brian Flood has just published a <a href="http://wave-map.appspot.com/" target="_blank">robot/gadget combo</a> that displays a map showing the locations of the wave participants using several different geolocation API&#8217;s and Google Maps. Here&#8217;s some information about <a href="http://code.google.com/apis/wave/extensions/robots/index.html" target="_blank">robots</a> and <a href="http://code.google.com/apis/wave/extensions/gadgets/guide.html" target="_blank">gadgets</a>. I don&#8217;t have sandbox access so I can&#8217;t test it but here are some preliminary comments.</p>
<ol>
<li>This is the first time I&#8217;ve seen a robot/gadget combo. The robot, when invited to a wave, automatically embeds a specialized gadget. This seems to be a simpler way to embed specialized content for a typical user than actually installing a gadget, and it allows the robot to place additional structure on the collaboration (for example, permissions). Robots can also access and modify the enclosing wave, whereas gadgets can only access the gadget state. I believe we will see many significant add-ons to Wave being bundled in this way.</li>
<li>We are starting to see how the underlying philosophy of Wave is affecting developers. In Wave, people can only access waves if they were invited to join them. This is in stark contrast to the current state of affairs in other social platforms on the Web (Facebook, Twitter). In Brian&#8217;s participant map, any participant must opt-in to share their location. We are gracefully entering the next phase of the Web &#8211; the phase of true participatory social networks, built on top of Wave.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/06/11/robotgadget-combo-participant-map/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New version of gadget emulator + A note on gadget states</title>
		<link>http://wave.thewe.net/2009/06/09/new-version-of-gadget-emulator-a-note-on-gadget-states/</link>
		<comments>http://wave.thewe.net/2009/06/09/new-version-of-gadget-emulator-a-note-on-gadget-states/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 14:30:27 +0000</pubDate>
		<dc:creator>Avital Oliver</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=31</guid>
		<description><![CDATA[The lastest version of the gadget emulator now shows the gadget state and supports an actual list of participants and quite a few of the sample gadgets are working now. I am current working with Patrick &#8220;p2k&#8221; Schneider to try to integrate this into his work on a wave server. There are still a few [...]]]></description>
			<content:encoded><![CDATA[<p>The lastest version of the <a href="http://wave.thewe.net/emulator" target="_blank">gadget emulator</a> now shows the gadget state and supports an actual list of participants and quite a few of the sample gadgets are working now. I am current working with Patrick &#8220;p2k&#8221; Schneider to try to integrate this into his work on a <a href="http://pygowave.p2k-network.org/" target="_blank">wave server</a>. There are still a few gadgets that don&#8217;t work because of unimplemented APIs on the emulator (_IG_Prefs and OpenSocial), but the current state of the emulator is enough for us to start creating some significant gadgets. If anyone feels that they would like this emulator to support additional APIs, feel free to participant by forking the <a href="http://github.com/avital/google-wave-gadget-emulator/tree/master" target="_blank">project on GitHub</a>.</p>
<p>On another note, Vidar&#8217;s attempt at an SVG editor has shown how hard it is to manage gadget state information when all you can use for values is strings (no arrays or objects). Vidar made an attempt to solve it in his gadget by encoding an array-like structure as keys of the form &#8220;svg_&lt;participant-id&gt;_&lt;index&gt;&#8221;. This is a good idea but it is still broken because:</p>
<ol>
<li>You can be logged in as the same user on multiple machines</li>
<li>This paradigm would not allow to add elements in the beginning or middle of an array</li>
</ol>
<p>I am starting to work on a gadget state management framework that should give you the feeling like you&#8217;re almost just working with plain Javascript objects and arrays when in fact is uses a crazy encoding scheme to make it work with Wave&#8217;s basic gadget state structure without breaking concurrency.</p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/06/09/new-version-of-gadget-emulator-a-note-on-gadget-states/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gadget emulator with real database</title>
		<link>http://wave.thewe.net/2009/06/06/gadget-emulator-with-real-database/</link>
		<comments>http://wave.thewe.net/2009/06/06/gadget-emulator-with-real-database/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 08:33:58 +0000</pubDate>
		<dc:creator>Avital Oliver</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wave.thewe.net/?p=6</guid>
		<description><![CDATA[Inspired by Vidar Hokstad&#8217;s two-iframes gadget emulator, I have created one that is actually backed up by a real database. It polls every 6 seconds for updates, so it&#8217;s not as immediate as Google&#8217;s (yet) but that would actually make it easier to discover concurrency problems with gadgets.
Each generated URL points to a specific gadget [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by Vidar Hokstad&#8217;s <a href="http://www.hokstad.com/google-wave-gadget-emulator.html" target="_blank">two-iframes gadget emulator</a>, I have created one that is actually backed up by a real database. It polls every 6 seconds for updates, so it&#8217;s not as immediate as Google&#8217;s (yet) but that would actually make it easier to discover concurrency problems with gadgets.</p>
<p>Each generated URL points to a specific gadget with a specific instance. You can share these URL&#8217;s on multiple machines (or windows if you are testing alone) and they will synchronize data.</p>
<p><a href="http://wave.thewe.net/emulator" target="_blank">http://wave.thewe.net/emulator</a></p>
<p>Code on GitHub: <a href="http://github.com/avital/google-wave-gadget-emulator/tree/master" target="_blank">http://github.com/avital/google-wave-gadget-emulator/tree/master</a></p>
]]></content:encoded>
			<wfw:commentRss>http://wave.thewe.net/2009/06/06/gadget-emulator-with-real-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
