Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example : how to create a revision #2

Open
mixmix opened this issue Sep 5, 2019 · 5 comments
Open

Example : how to create a revision #2

mixmix opened this issue Sep 5, 2019 · 5 comments

Comments

@mixmix
Copy link

mixmix commented Sep 5, 2019

hey @regular , I'm looking at your work again because it might be super relevant to something I'm starting in on. I've read your README (very good docs thank you!), and one thing I'm missing is an example of how it's like to create revisions. I thought I'd write an example for myself, and it might turn out to be useful for others too!


Story. I publish a profile for a place of cultural significance. It has content like this:

// content of message %A  (a made up abbreviated key for ease of reading)
{
  type: 'profile',
  title: 'Mount Victoria',
  description: 'this is a beautiful little hill overlooking wellington'
}

Someone publishes a comment:

// content of message %B
{
  type: 'post',
  text: 'do not go up there when it is windy',
  root: '%A',
  branch: ['%A']
}

Then I edit the original profile message by publishing this revision message

// content of message %C
{
  type: 'profile',
  title: 'Mount Victoria',
  description: 'this is a beautiful little **dormant volcano** overlooking wellington',
  root: '%A',
  branch: ['%B'],
  revisionRoot: '%A',
  revisionBranch: ['%A']
}
@mixmix mixmix changed the title Example : how to create a mutation Example : how to create a revision Sep 5, 2019
@mixmix
Copy link
Author

mixmix commented Sep 5, 2019

Things I'm not sure about in the above story:

1. do you need to publish all fields on the revision, or can you just publish the changes ?
i.e :

{
  description: 'this is a beautiful little **dormant volcano** overlooking wellington',
  root: '%A',
  branch: ['%B'],
  revisionRoot: '%A',
  revisionBranch: ['%A']
}

I don't expect this will work because the type property is required yes. I also suspect that this might be asserting that the title should be removed?
Yeah I guess I'm unclear what the reduction looks like.

2. what does branch represent for revisions?
The way I'm visualising this is that there are 2 orderings going on

  • the causal ordering of all messages contributing to the document (root, post, edit)
  • the causal ordering of the revisions on a particular message
all messages 
 |        %A
 |         |
 |         v
 |        %B
 |         |
 |         v
 v        %C   (C says it happened after B)
revisions --------->

           %A --> %C  (C says it's the first edit on A)

           %B

@mixmix
Copy link
Author

mixmix commented Sep 5, 2019

Do you have methods anywhere for publishing revisions?

It's my strong opinion that helpers to handle these details for developers are the best pattern. Many people don't understand things like branch and implement it incorrectly.
Of course this is open source and you're not obliged to write anything for people but I wanted to share my experience.

Here's an example of a helper which calculates branch for a user who wants to update a gathering

@regular
Copy link
Owner

regular commented Sep 5, 2019

Hey @mixmix thanks!

  1. what does branch represent for revisions?

Revisions don't alter the semantics of root and branch properties. If you post a revision with branch and root, it will simply change the branch and root of the original message, i.e. it will change what posting you replied to in the thread or even the thread your reply is in. In your example, there is no need to have these properties in the revision. (ah, and it would not be possible to refer to %B inside of %B, because the actual message key will only be known after posting ...)

// content of message %C
{
  type: 'profile',
  title: 'Mount Victoria',
  description: 'this is a beautiful little **dormant volcano** overlooking wellington',
  revisionRoot: '%A',
  revisionBranch: ['%A']
}

would be sufficient.

In tre I use root and branch for a file-system like tree of objects. So, branch is changed in response to dropping a file to a different folder.

Do you have methods anywhere for publishing revisions?

I think I have such a helper hidden in tre-client ... (bad place for it, I know)
Yea, it's here, monkey-patching ssb.revisions ... well.

I'd probably prefer to keep convenience method in a separate module (separate from ssb-revisions) because I suspect their API to change more frequently than ssb-revision's, which should remain relatively stable and a small API surface helps with that.

  1. do you need to publish all fields on the revision, or can you just publish the changes ?

Yes, there is no support for deltas or diffs, you have to post the entire message. This means that you have to include large property values even if they have not changed. The reasona behind this

  1. it's simple
  2. There's no guarantee that you have the entire history of a message. You might block the author of a revision in between or they might just not be in your scuttle horizon. In this case a diff-based system would not be able to give you the latest version even if you follow the person that postet the newest revision.

That having said, I have a change-permission scheme in mind (well, dominic came up with it way back), where you list the ssb-feeds that should have permission to change you message in that message's editors property.

{
  type: "todo",
  title: "Things we have to prepare for the camp",
  editors: ["@jhdfjkshdf", "@sdfklsdf"]
  items: [ ... ]
}

Of course, the editors field itself can be edited by editors (read: they can invite new people to collaborate on the document). For a client to decide, whether a given revision is legit, it would have to look at the editor value in the preceding revision, and then to know if that preceding revision was legit, it would have to recurse to the one before, all the way to the original message. So here's a similar use case that suffers from the incomplete history problem. For some scenarios (my museum stuff for example), incomplete history might never occur, and there diffs and editors would be very nice features.

It would be interesting to build a proof of concept for, say a lodash.merge-based reduction.

@mixmix
Copy link
Author

mixmix commented Sep 6, 2019

I've built a merge-based reduction in scuttle-gatherings ... each thing getting merged gets a little filtering for "legal" edits (in my case means parseable/ correct format / allowed property, but could be extended to mean "allowed author").

Yeah I've thought about this editor field as well. In this case I think about the editors less as a field and more like a timeline with editors being added / removed for parts of it... and edits that were made being legal within the bounds that an editor was "on board". I think this is the same things you're describing with recursion. Juicy huh.

A further idea I'm considering is to make the editor field point to another message / document (somewhere else) which is a "group" definition. I want this because I think for my case I'm going to need to confer authorship to many different documents at once, and I think it would be a nightmare to maintain without editors being abstracted. Not sure how to do this.

Happily, I'm hosting Dominic at my house this coming week, and I plan to get all the downloads on the private group work (which will also intersect with this work in the future I think). All the things....can't just be simple huh.

Would be nice to catch up some time and hear about your adventures over the last year!

@mixmix
Copy link
Author

mixmix commented Sep 6, 2019

I've been writing about this on ssb : %tqk8p2DTokSzrzmIvFqu8v6gHD23I0F1Fy5ILLfF2jI=.sha256

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants