New version with slightly more correct cached edit handling. And I've added
a third client that is being a spam bot.

The state trace now looks like this:

Three clients, sync'd
server editHistory[0]:
Client 'Client1' at server revision 1 with document
Client 'Client2' at server revision 1 with document
Client 'Client3' at server revision 1 with document

Client3 is generating noise
server editHistory[0]:
server editHistory[1]: ++" Chatter";
Client 'Client1' at server revision 1 with document
Client 'Client2' at server revision 1 with document
Client 'Client3' at server revision 2 with document ++" Chatter";

Client2 has generated an edit, and it's in flight
server editHistory[0]:
server editHistory[1]: ++" Chatter";
Client 'Client1' at server revision 1 with document ++"Hello";  with edit in
flight ++"Hello";
Client 'Client2' at server revision 1 with document
Client 'Client3' at server revision 2 with document ++" Chatter";

Client2 has generated matching edit, also in flight
server editHistory[0]:
server editHistory[1]: ++" Chatter";
Client 'Client1' at server revision 1 with document ++"Hello";  with edit in
flight ++"Hello";
Client 'Client2' at server revision 1 with document ++"Hello";  with edit in
flight ++"Hello";
Client 'Client3' at server revision 2 with document ++" Chatter";

Client1 has handbasket edit cached
server editHistory[0]:
server editHistory[1]: ++" Chatter";
Client 'Client1' at server revision 1 with document ++"Hello";  with edit in
flight ++"Hello";  with cached edit __5; ++" Going to hell";
Client 'Client2' at server revision 1 with document ++"Hello";  with edit in
flight ++"Hello";
Client 'Client3' at server revision 2 with document ++" Chatter";

Server has client2's edit in, and clients synced there
server editHistory[0]:
server editHistory[1]: ++" Chatter";
server editHistory[2]: ++"Hello"; __8;
Client 'Client1' at server revision 3 with document ++"Hello Chatter";  with
cached edit __5; ++" Going to hell"; __8;
Client 'Client2' at server revision 3 with document ++"Hello Chatter";
Client 'Client3' at server revision 3 with document ++"Hello Chatter";

Client3 is generating noise
server editHistory[0]:
server editHistory[1]: ++" Chatter";
server editHistory[2]: ++"Hello"; __8;
server editHistory[3]: __13; ++" Chatter";
Client 'Client1' at server revision 3 with document ++"Hello Chatter";  with
cached edit __5; ++" Going to hell"; __8;
Client 'Client2' at server revision 3 with document ++"Hello Chatter";
Client 'Client3' at server revision 4 with document ++"Hello Chatter
Chatter";

Server accepts client1's edit
server editHistory[0]:
server editHistory[1]: ++" Chatter";
server editHistory[2]: ++"Hello"; __8;
server editHistory[3]: __13; ++" Chatter";
server editHistory[4]: ++"Hello"; __21;
Client 'Client1' at server revision 3 with document ++"Hello Chatter";  with
cached edit __5; ++" Going to hell"; __8;
Client 'Client2' at server revision 3 with document ++"Hello Chatter";
Client 'Client3' at server revision 4 with document ++"Hello Chatter
Chatter";

Client3 is generating noise
server editHistory[0]:
server editHistory[1]: ++" Chatter";
server editHistory[2]: ++"Hello"; __8;
server editHistory[3]: __13; ++" Chatter";
server editHistory[4]: ++"Hello"; __21;
server editHistory[5]: __26; ++" Chatter";
Client 'Client1' at server revision 3 with document ++"Hello Chatter";  with
cached edit __5; ++" Going to hell"; __8;
Client 'Client2' at server revision 3 with document ++"Hello Chatter";
Client 'Client3' at server revision 6 with document ++"HelloHello Chatter
Chatter Chatter";

Client1's cached edit posted to server, and accepted
server editHistory[0]:
server editHistory[1]: ++" Chatter";
server editHistory[2]: ++"Hello"; __8;
server editHistory[3]: __13; ++" Chatter";
server editHistory[4]: ++"Hello"; __21;
server editHistory[5]: __26; ++" Chatter";
server editHistory[6]: __10; ++" Going to hell"; __24;
Client 'Client1' at server revision 7 with document ++"HelloHello Going to
hell Chatter Chatter Chatter";
Client 'Client2' at server revision 7 with document ++"HelloHello Going to
hell Chatter Chatter Chatter";
Client 'Client3' at server revision 7 with document ++"HelloHello Going to
hell Chatter Chatter Chatter";

>From my perspective, the above shows that this simple c/s protocol based on
pushing edits to the server, and pulling a queue of edits back in separate
c->s calls, works. I'm not happy with how i'm modeling cached edits in the
client at this point, which means I need to re-do Client#acceptUpdates(),
probably using a strategy pattern...

brett

On Thu, Jan 21, 2010 at 10:28 AM, Brett Morgan <[email protected]>wrote:

> Ugh.
>
> Reading back through my code after breakfast, and I realise that i'm
> handling the cached edit while an edit is in flight incorrectly. And my
> initial stabs at fixing it up are breaking. I think i need a bigger piece of
> paper to figure this out...
>
> brett
>
> 2010/1/21 Brett Morgan <[email protected]>
>
> Heya Torben,
>>
>> I have attached a java class that I believe implements Daniel's scenario.
>> First off, note that I'm not implementing the wave federation algorithm, as
>> federation isn't my goal. My goal is to build web apps that use wave's OT.
>> That said, here is the output of the aforementioned java class showing that
>> the server and the two clients converge.
>>
>> State of system after step 1
>> server editHistory[0]:
>> Client 'Client1' at server revision 1 with document
>> Client 'Client2' at server revision 1 with document
>> State of system after step 2
>> server editHistory[0]:
>> Client 'Client1' at server revision 1 with document ++"Hello";  with edit
>> in flight ++"Hello";
>> Client 'Client2' at server revision 1 with document
>> State of system after step 3
>> server editHistory[0]:
>> Client 'Client1' at server revision 1 with document ++"Hello";  with edit
>> in flight ++"Hello";
>> Client 'Client2' at server revision 1 with document ++"Hello";  with edit
>> in flight ++"Hello";
>> State of system after step 4
>> server editHistory[0]:
>> Client 'Client1' at server revision 1 with document ++"Hello";  with edit
>> in flight ++"Hello";  with cached edit __5; ++"Going to hell";
>> Client 'Client2' at server revision 1 with document ++"Hello";  with edit
>> in flight ++"Hello";
>> State of system after step 5
>> server editHistory[0]:
>> server editHistory[1]: ++"Hello";
>> server editHistory[2]: ++"Hello"; __5;
>> Client 'Client1' at server revision 2 with document ++"Hello";  with
>> cached edit __5; ++"Going to hell";
>> Client 'Client2' at server revision 2 with document ++"Hello";
>> State of system after step 7
>> server editHistory[0]:
>> server editHistory[1]: ++"Hello";
>> server editHistory[2]: ++"Hello"; __5;
>> server editHistory[3]: __10; ++"Going to hell";
>> Client 'Client1' at server revision 4 with document ++"HelloHelloGoing to
>> hell";
>> Client 'Client2' at server revision 4 with document ++"HelloHelloGoing to
>> hell";
>>
>>
>>  On Thu, Jan 21, 2010 at 7:15 AM, Torben Weis <[email protected]>wrote:
>>
>>> Hi Brett,
>>>
>>> thanks for the hint to your project. I did not know it before.
>>>
>>
>> It had it's coming out party at LCA. And I think I'm going to rip it down
>> and start again, this time using long poll based notification. I couldn't do
>> long polls while I was targeting AppEngine as my deployment environment.
>>
>>
>>> However, I would like to see a proof (i.e. a short explanation is
>>> sufficient) how you intend to solve the problem I have mentioned.
>>> Running code is no proof :-)
>>>
>>
>> If running code doesn't merit existence proof status, then i'm fucked. =)
>>
>>
>>> For some reasons I strongly doubt that your code (or any possible code)
>>> can handle this without changes to the C/S protocol.
>>>
>>
>> The client/server protocol in the FedOne code base, unless i miss my
>> guess, isn't doing OT.
>>
>>
>>> Your application seems to be different anyway. If I am not mistaken (I
>>> just read the wave you mentioned) you are running
>>> a web client which connects to your web server which connects to FedOne.
>>> Right?
>>>
>>
>> Heh, no. I'm not using FedOne, just the OT component of FedOne. I'm
>> building out the capacity to be able to have gwt web clients running OT sync
>> with a webserver. It works, but I lack the theoretical grounding to prove
>> it.
>>
>>
>>> The problem I mentioned is between your web server and FedOne. In my case
>>> it is between QWaveClient and FedOne.
>>> Your web app can of course recover as long as FedOne and your web server
>>> are stable. But what happens if your
>>> WebServer crashes in an unfortunate moment? Your code will suffer from
>>> the very problem I described.
>>>
>>
>> If the web server goes down with unsync'd state, everything goes shiny. At
>> this point I force the clients to drop all state and reload.
>>
>>
>>> However, would like to be proven wrong here since this would give me a
>>> solution to my initial problem :-)
>>>
>>
>> Sorta, kinda, maybe.
>>
>>
>>> Greetings
>>> Torben
>>>
>>> 2010/1/20 Brett Morgan <[email protected]>
>>>
>>>> Actually, no, OT deals with this case. My almost working code that I
>>>> presented at LCA2010 deals with this edge case. Unfortunately it has bugs,
>>>> and dies in the arse randomly. Sigh.
>>>>
>>>> Wave that I presented from:
>>>>
>>>> https://wave.google.com/wave/#restored:wave:googlewave.com!w%252BTBvx4ehoA<https://wave.google.com/wave/#restored:wave:googlewave.com%21w%252BTBvx4ehoA>
>>>> The code:
>>>>
>>>> http://code.google.com/p/wave-ot-editor/source/browse/#svn/wave-ot-editor
>>>>
>>>> I can put together a JUnit test case showing that this case actually
>>>> stabilises using the Wave OT code, if that would help...
>>>>
>>>>
>>>> On Wed, Jan 20, 2010 at 11:40 AM, Torben Weis <[email protected]>wrote:
>>>>
>>>>> Hi Brett,
>>>>>
>>>>> thanks for the suggestion.
>>>>> However, it seems to me that this approach is not completely correct.
>>>>>
>>>>> Imagine two clients which are sending a delta against the same server
>>>>> version.
>>>>> The delta says to insert "Hello" at some position in a blip.
>>>>> The correct outcome is "HelloHello" being inserted.
>>>>> Now one client fails to submit its delta, the other one succeeds.
>>>>> The client that failed cannot detect that it failed, because the other
>>>>> delta looks exactly the same. Thus, in the end "Hello" will be inserted
>>>>> only once.
>>>>>
>>>>> I agree that this is an academic corner case, but I see no solution for
>>>>> this
>>>>> when relying on delta comparisons.
>>>>>
>>>>> Greetings
>>>>> Torben
>>>>>
>>>>>
>>>>> 2010/1/19 Brett Morgan <[email protected]>
>>>>>
>>>>>> If you are transforming your docops, you can compare the docops coming
>>>>>> back down for equality. You are doing client side transformations, right?
>>>>>>
>>>>>> org.waveprotocol.wave.model.operation.OpComparators is the FedOne code
>>>>>> for comparing equality of ops. Which, after a whole bunch of edge case
>>>>>> checking turns into the following comparison:
>>>>>>
>>>>>> DocOpUtil.toConciseString(a).equals(DocOpUtil.toConciseString(b))
>>>>>>
>>>>>> In short, comparing docops for equality is easy, as long as you keep
>>>>>> transforming your docops...
>>>>>>
>>>>>>  On Wed, Jan 20, 2010 at 9:42 AM, Torben Weis 
>>>>>> <[email protected]>wrote:
>>>>>>
>>>>>>>  Hi James,
>>>>>>>
>>>>>>> How about when the client connects to the server again it does a
>>>>>>>> history
>>>>>>>> check against the known good deltas it has sent out. If the last
>>>>>>>> delta
>>>>>>>> it sent out isn't in the history, then it hasn't been received.
>>>>>>>>
>>>>>>>
>>>>>>> The problem is that this is impossible. How should QWaveClient
>>>>>>> recognize a delta as
>>>>>>> being its own? The server has perhaps transformed the delta, i.e.
>>>>>>> simple delta comparison
>>>>>>> is not possible and looking at version numbers does not help either.
>>>>>>>
>>>>>>> Greetings
>>>>>>> Torben
>>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>>
>>>>>>>> James Purser
>>>>>>>> http://wavingtheshiny.collaborynth.com.au
>>>>>>>> Wave Addresses:
>>>>>>>> [email protected] (wave.google.com)
>>>>>>>> [email protected] (wavesandbox.com)
>>>>>>>> [email protected] (collaborynth.com.au FedOne Server)
>>>>>>>> Skype: purserj1977
>>>>>>>> GTalk: [email protected]
>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>> Groups "Wave Protocol" group.
>>>>>>>> To post to this group, send email to [email protected]
>>>>>>>> .
>>>>>>>> To unsubscribe from this group, send email to
>>>>>>>> [email protected]<wave-protocol%[email protected]>
>>>>>>>> .
>>>>>>>> For more options, visit this group at
>>>>>>>> http://groups.google.com/group/wave-protocol?hl=en.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> ---------------------------
>>>>>>> Prof. Torben Weis
>>>>>>> Universitaet Duisburg-Essen
>>>>>>> [email protected]
>>>>>>>
>>>>>>> --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "Wave Protocol" group.
>>>>>>> To post to this group, send email to [email protected].
>>>>>>> To unsubscribe from this group, send email to
>>>>>>> [email protected]<wave-protocol%[email protected]>
>>>>>>> .
>>>>>>> For more options, visit this group at
>>>>>>> http://groups.google.com/group/wave-protocol?hl=en.
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Brett Morgan http://domesticmouse.livejournal.com/
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "Wave Protocol" group.
>>>>>> To post to this group, send email to [email protected].
>>>>>> To unsubscribe from this group, send email to
>>>>>> [email protected]<wave-protocol%[email protected]>
>>>>>> .
>>>>>> For more options, visit this group at
>>>>>> http://groups.google.com/group/wave-protocol?hl=en.
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> ---------------------------
>>>>> Prof. Torben Weis
>>>>> Universitaet Duisburg-Essen
>>>>> [email protected]
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Wave Protocol" group.
>>>>> To post to this group, send email to [email protected].
>>>>> To unsubscribe from this group, send email to
>>>>> [email protected]<wave-protocol%[email protected]>
>>>>> .
>>>>> For more options, visit this group at
>>>>> http://groups.google.com/group/wave-protocol?hl=en.
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Brett Morgan http://domesticmouse.livejournal.com/
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Wave Protocol" group.
>>>> To post to this group, send email to [email protected].
>>>> To unsubscribe from this group, send email to
>>>> [email protected]<wave-protocol%[email protected]>
>>>> .
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/wave-protocol?hl=en.
>>>>
>>>>
>>>
>>>
>>> --
>>> ---------------------------
>>> Prof. Torben Weis
>>> Universitaet Duisburg-Essen
>>> [email protected]
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Wave Protocol" group.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected]<wave-protocol%[email protected]>
>>> .
>>> For more options, visit this group at
>>> http://groups.google.com/group/wave-protocol?hl=en.
>>>
>>>
>>
>>
>> --
>> Brett Morgan http://domesticmouse.livejournal.com/
>>
>
>
>
> --
> Brett Morgan http://domesticmouse.livejournal.com/
>



-- 
Brett Morgan http://domesticmouse.livejournal.com/
--
You received this message because you are subscribed to the Google Groups "Wave Protocol" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected].
For more options, visit this group at http://groups.google.com/group/wave-protocol?hl=en.

Attachment: Breakage.java
Description: Binary data

Reply via email to