automerge / automerge-classic

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.
http://automerge.org/
MIT License
14.75k stars 466 forks source link

Primitive OpId datatype to reference Automerge operations/objects #402

Closed rmst closed 3 years ago

rmst commented 3 years ago

Currently, Automerge operations and objects can be referred to by their OpId which is a string of the form ${counter}@${actorId}. To refer to these ids within an Automerge document (e.g. for linking between notes) it might be nice to introduce a dedicated primitive datatype in the binary format. This would allow Automerge to automatically update the ids in case their format changes. The interface could look as follows.

Automerge.change(doc0, doc => {
  doc.linkToNote = OpId("3@actorId")
}
ept commented 3 years ago

Hi @rmst, thanks for this suggestion. We could definitely introduce an OpId datatype and use the existing binary format's encoding to store them in a compact and future-proof representation. The simplest API, which you're suggesting, would be to expose an OpId to the application as a string (wrapped in an OpId object), but I wonder if we should go further than that in the API: an OpId is quite a low-level concept, and maybe what is needed is actually a higher-level abstraction?

The operation that an OpId points to could be a bunch of different things. If it points at an object creation operation, then the OpId is the ObjectID of that object, and you can use Automerge.getObjectById() to get an instance of that object. If it points at a list insertion operation, it's very similar to a cursor (#313), which is a pointer to a particular list element that automatically computes the current index of that element. But the OpId could also point at a field assignment op, or an increment op, in which case its meaning is less clear. All of this means an OpId is probably not an easy-to-use abstraction.

If your primary use case is linking between objects, one existing method you can use is Automerge.Table, which is a collection that gives every element a UUID primary key. You can then use those UUIDs just like you would use foreign key references in a relational database, or to create edges between vertices in a graph data model. For linking notes, like you suggest, I think that would be a reasonable approach.

Is there a reason why the Automerge.Table approach is not suitable for your application?

rmst commented 3 years ago

You're right. Like I said in the Automerge Slack

I'm actually not so sure about the use case that I gave in the issue. Linking between notes might be better realized at a higher level with application defined ids. Perhaps this issue can be ignored until somebody comes up with a better use case.

There might be use cases that might benefit from a general OpId interface but I don't have a concrete one at the moment.

ept commented 3 years ago

Okay, thanks for clarifying. My priorities are currently on features for which we have a clear need and which can't sensibly be provided outside of Automerge core. Since that is not the case for this feature, I am going to close this issue until further evidence of a need emerges.