Thats a good idea.

Lets say I'm editing a small C project in my IDE. Lets say the project
is being stored as one big JSON object (including the text of all
files). I have another process which is periodically saving out any
updated files to disk.

My document might look like this:

{
  "name": "librope",
  ... Compiler options, etc.
  "files": {
    "src": {
      "rope.c": { "text": "#include <rope.h>\n ..." },
      "rope.h" { "text": "// This is a cool header"  },
    },
    "resources": {... more files .... }
  }
}

Lets say I want to move src/rope.h to the resources directory. I drag
the file in my IDE, which does an object move operation to move the
files/src/rope.h to files/resources/rope.h. This is fine, and will
work fine.

My worry is that if someone else moves another file called rope.h to
the resources directory at the same time, I don't want the result to
ever be that one of our files gets deleted from disk.

Some observations:
- This will almost never actually happen in real life.
- Even if we turn the operation will transform into a 'replace', we
could add a flag to the operation to mark that it was unintentionally
overwritten, and then the process which is making the corresponding
changes on disk could see that and do some special
application-specific behaviour instead of actually deleting the file.

-J

On Mon, Oct 20, 2014 at 8:27 PM, Michael MacFadden
<michael.macfad...@gmail.com> wrote:
> Joseph,
>
> I¹d like to drill into the directory structure mapping concept a bit.  Can
> you epand on the use case where you think ShareJS would be used to map to a
> directory structure?  I think thing this would help us understand some of
> the challenges.
>
> ~Michael
>
> From:  Richard Davis <richardc...@gmail.com>
> Reply-To:  <wave-dev@incubator.apache.org>
> Date:  Monday, October 20, 2014 at 6:53 PM
> To:  <shar...@googlegroups.com>
> Cc:  <wave-dev@incubator.apache.org>, <derb...@googlegroups.com>
> Subject:  Re: JSON editing and move conflicts
>
> Hi Joseph,
>
> Regarding object move, I'm in favor of keeping things simple, but I'm also
> in favor of thinking about this in terms of what people might actually do
> with this capability. Since mapping a directory structure of files is the
> one good example you have, then maybe multiple moves to the same key should
> merge their values as directory moves merge their files. That would mean a
> slightly modified version of your option 1. In the simple case, you have
> {x:1, y:2} -> {z:2}, but in the complex case you have {x:{a:1}, y:{b:2}} ->
> {z:{a:1, b:2}}.
>
> Maybe you could add a flag that allows the writer to specify whether they
> want a move to "replace" the existing value (your option 1) or "merge" with
> the existing value (this modified option 1). It's still clear what will
> happen if two writers use two different flags, as long as you can put the
> two ops in some order: if the "replace" comes second you can replace, and if
> the "merge" comes second you can merge.
>
> The only downside I see of merging is that it can have a cascading effect.
> That could be tricky, and I haven't thought it through, but I had hope that
> this wouldn't be fundamentally different from the other changes you are
> making in JSON2.
>
> -Richard
>
> On Sunday, October 19, 2014 8:46:11 AM UTC+8, Joseph Gentle wrote:
>> It does complicate the type, and it breaks my nice abstraction. Also
>> remember that any funny logic will need to be on the server and the
>> client - and I'd really like the server to be application-agnostic if
>> possible. That said, the server will probably need
>> application-specific schema validation & access control code anyway,
>> so maybe its not a big deal.
>>
>> Another option is to just do the dangerous thing for objects, but
>> actively encourage people to use lists instead. If you're inserting
>> into a list instead of inserting into an object, the semantics are
>> safe & easy. The final list will just contains both items. For
>> hierarchal to-do lists, you probably want a children:[] list on your
>> nodes anyway. Using object-move when the key is either a GUID or a
>> hash of the data would work fine as well because your keys won't
>> conflict.
>>
>> This won't work if you're trying to map a directory structure of files
>> though. But thats the only bad use case I can think of. Maybe
>> something as simple as a flag on the move operation saying "in the
>> case of conflicts, rewrite the destination key to {key}_n". Or we
>> could just force the IDE to use a list of files, and leave deduping
>> hacks there.
>>
>> -J
>>
>>
>>
>> On Sat, Oct 18, 2014 at 4:44 PM, Ali Lown <a...@lown.me.uk <javascript:> >
>> wrote:
>>> > Hi Joseph,
>>> >
>>> > I think that the only sensible option is to delegate the resolution of
>>> > this action in the case of conflict back into the application, so some
>>> > sort of extension of (4) that allows some arbitrary lambda expression
>>> > to be passed as the onconflict method. (Depending on the situation,
>>> > they might want to 'merge' the two items (if possible), rather than
>>> > moving one into a 'backup' location).
>>> >
>>> > This does complicate the OT type, and does make it more difficult to
>>> > analyse how long certain actions will take to resolve though...
>>> >
>>> > How does this sound?
>>> >
>>> > Ali
>>> >
>>> > On 19 October 2014 00:33, Joseph Gentle <jos...@gmail.com <javascript:> >
>>> wrote:
>>>> >> I'm (finally!) taking a serious look at making a better version of the
>>>> >> JSON OT type. I'm cross-posting this here because it directly effects
>>>> >> sharejs & derby users, and I think any serious rewrite of wave will
>>>> >> use something like this at the top level to store waves.
>>>> >>
>>>> >> I have two questions that I would love some input on from the wider
>>>> community.
>>>> >>
>>>> >> We want to add a 'move' action which will let you transplant arbitrary
>>>> >> parts of the JSON structure to other places in the tree. This is
>>>> >> really useful if, for example, you want a hierarchal to-do list, a
>>>> >> tree of source files for your IDE or a tree of blips.
>>>> >>
>>>> >> But I can't figure out what should happen if two users move different
>>>> >> objects to the same place in the tree at the same time.
>>>> >>
>>>> >> 1. The simplest option is to simply delete one of them. This is really
>>>> >> convenient from a programming pov, but I think that would be the worst
>>>> >> kind of surprise. {x:1, y:2} -> {z:2}
>>>> >> 2. We could try and make one of the moves fail - {x:1, y:2} -> {x:1,
>>>> >> z:2}. On the face of it this sounds great, but this is a cascading
>>>> >> failure. If (locally) I move x->z then insert some new data at x, what
>>>> >> happens to the new data? Does the new data get deleted? Does x get
>>>> >> deleted? I can't think of a good answer here which isn't just
>>>> >> dangerous in a more complicated way. Making both the moves fail has
>>>> >> the same problem.
>>>> >> 3. We could pick a winner and then move the loser to some special
>>>> >> lost&found bucket or something. So, {x:1, y:2} -> {__recovered_z:1,
>>>> >> z:2} But that could play havoc with data bindings, and we'd have to
>>>> >> introduce some reserved keys. The other way to do this is to introduce
>>>> >> a new top-level structure which contains the data, so it'd be
>>>> >> {data:{x:1, y:2}} -> {data:{z:2}, lost:[{z:1}]}.
>>>> >> 4. Or we could add the backup location into the move operation itself,
>>>> >> so whoever's building on top of this API can make the choice. (They
>>>> >> can make a better decision because they know what the data structure
>>>> >> looks like). So instead of (move x->z) we'd have (move x->z,
>>>> >> onconflict:(move x->__x)) or something.
>>>> >>
>>>> >> Are there any other choices I'm missing here? I'm edging toward option
>>>> >> 4, although it might increase the type's complexity by 50% unless I
>>>> >> can think of a clean way to do it.
>>>> >>
>>>> >> Thanks
>>>> >> -J
>
>

Reply via email to