Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Editable entities #94
I started with this some time ago (and already discussed parts of it with @annando over a year ago), but didn't have the time to finish it until now.
This adds basic edit features to the protocol:
Not all properties are editable (for example you can't change the
Related to: diaspora/diaspora#1762
So, I'm not sure we do want this backward compatible actually. Perhaps not even to the point that anything still works with an incompatible implementation. Having one side send edits and the other side silently ignoring them seems like a major UX fuckup to me, wouldn't it be very very confusing?
Maybe "backward compatible" was the wrong word, but it's without the need of inviting something completely new. But how do you want to prevent that somebody ignores your message? Even when you invite something completely new, but when one system sends it to another system that doesn't understand it yet (maybe it's not implemented yet, or it's an old version and not updated yet), there is nothing other than that you can do than fail/ignore the message, but the sender already did the action.
Yeah, doing something that isn't supported by everybody isn't great, that's why we try to wait until some servers support it until we add the frontend (for examply only adding the account migration/import after other servers already can process the migrate message), but there will always be servers which don't support it (and silently ignore it).
We already have these "major UX fuckups" today:
So we have this problem all over the place, but I have no idea how you want to solve this?
Well, all of your examples are missing content. This would introduce wrong/inconsistent content. Breaking backwards compatibility could be an incentive to for the ecosystem to upgrade quicker. This doesn't have to be a single step, like before we could introduce forward compatibility early and stop sending backward compatible messages only a major release later.
Yes, there are maybe more things that work differently, but that was just what came to my mind in two minutes ;)
This only adds a unnecessary breaking change for everybody (means more stress for other devs and podmins), and I think it wouldn't make a big difference in how consistent this feature works. Sure, we could add a
I also think that socialhome already supports editing, but they just resend the current
And even if everybody would implement this correctly, it wouldn't guarantee that everybody who has the original post would receive the edit (it's the same as nowadays not everybody who has the post receives comments for it). I have other ideas to fix that problem, but that's not related to the edit feature.
So I think this only makes the whole thing overly complicated, but doesn't add a benefit. People are used that things sometimes aren't consistent for different reasons (because we are a federated system). I'm working on making this better, but adding a breaking change where it isn't needed would make the whole situation even worse, and I don't like that. Some people wouldn't receive the original post then at all, instead of just not receiving the edit (which maybe not even happens, because the original post doesn't contain a typo, so no edit needed).
But with this little change we would have a clean specified way to send edits with a timestamp, and everybody who does it the same way, can profit from it (that's why I want to have it in the documentation, so everybody can do it the same way). It doesn't make the current situation worse (because we are already inconsistent, even with edits, see socialhome), but it allows to make the future better, because we can be more consistent then.
When implementing this at diaspora, we can discuss there, if we want to wait a major release until we allow the users to edit their post, after we implemented the backend/frontend for receiving and displaying edits (after we added forward compatibility). But that discussion doesn't belong here and we don't need to break the protocol for everybody else if only we want to wait.
Yes, thanks for that. And I thought about it, but I just couldn't find another solution than break it (to make sure nobody can receive a post that's maybe edited in the future), and that just doesn't sound like a good solution to me. And the problem will solve itself with time, the more pods update.
I don't think its necessary to store that kind of extra information in the protocol itself.
In my opinion all further logic should be handled by the application server.
I think that is exactly how @annando does it in friendica right now.
Just wanted to throw my hat in the ring,
When reusing the
So I think the additional property is necessary. Also the
So basically we have two types of editable entities. First type contain uneditable
These two types imply a little bit different logic. For entities with
Should we keep the mandatory
If we already know the original entity there is no much reason to send
But what do we do if we receive the edit when we didn't have the original entity in the first place? Do we fetch the original post explicitly? If so then we don't need
Then. How do we uniquely identify revisions? Do we want to support functionality of fetching an arbitrary revisions of an entity? Or it is enough to support of fetching of the first and the last versions only?
If we want to fetch an arbitrary revision, then we need a unique identifier of a revision. Currently the only thing that identifies a revision is a
Also how do we fetch a specific edit then? Do we use a route that includes the timestamp? Can't we then fetch different edits from the same second?
Also you introduce a concept of an editable field in the protocol. What if instead of having uneditable
Another approach I think of and I like it more, is not to include the absolute edit time to each entity, but rather include the number of seconds passed since the last (or the first?) revision of the entity. This way we could avoid handling weird situations where the edit is older than the original post for some reason. In the case when we don't have mandatory
And speaking about fetching. If we want to allow fetching of every revision, then we could make use of keeping an incremental revision number. Say that you have revisions 1,2,3 of the post and you suddenly receive revision number 5. Without having revision numbers in the entities we couldn't even know that there was a revision 4, because we only see dates. And even if we knew the specific date of some revision we would request a revision by its timestamp which feels clumsy. So if we want to have a possibility of fetching any revision then we should consider assigning incremental numbers for them.
That's nothing I see as complete proposals, but rather things to consider as potentially better approaches.
Also concerning the implementation, I would definetely support having an
Okay, here I structured my thoughts a little bit better. This is more like a proposal :)
So basically with my proposals we divide editable entities to two types: "wiki" entities and "overridable" entities. "wiki" entities have revision numbers,
For "wiki" entities the original version is one that:
and the edit
For "overridable" entities the format of edit is just the same as of the original entity.
Here is a tl;dr of why I did it the way I did:
And now a bit more verbose as response to your proposal:
They don't need it, but we need
Yes, because when fetching them we need it.
Yes, but the redundant
You can't fetch the original post, because the fetch specification doesn't support revisions. Also when a project just overwrites the original and doesn't keep revisions, the original doesn't exist anymore.
Some properties aren't allowed to change, but I want to always send a complete message. Yes, some information is redundant, but it doesn't matter, and I don't want to rely on that others already know it.
Also allowing missing mandatory properties in the case of an edit would make the validation much more complicated, and I want to keep it as simple as possible.
Se above: I don't want to force others to store revisions, so you can only fetch the last version.
If a script does multiple edits to the same entity in the same second I just don't care (about the fact that edits are messed up in this case). We probably need to do something against spam in this case, but I don't care about scripts. And humans probably need at least a second to edit a post or comment.
That's probably really an edge case. But:
In the NTP edge case, the time difference would end at 0 seconds if NTP sets the time to the exact same second as the original post.
Also this could easily break, or been implemented wrong. When you miss the last edit, and we define it as seconds since the last edit, you would calculate the wrong timestamp. And if we define it as seconds since the original, but somebody implements it wrong and uses the last edit, we would again have the wrong timestamp. While just having the timestamp is clear and easy, no calculation needed.
This should never happen, and if it happens, I don't care. The current protocol relies on the fact that the servers have the correct time. If timestamps for
This would be a breaking change, and as said, I don't want to break if, if it isn't really needed. Also I think the implementation would be more complicated when you have one field with different meanings.
I didn't respond to other revision number related proposals, because I don't want to enforce to store every revision. So every project implementing the protocol can decide if they want to store the old revisions (like on discourse) or just overwrite them and only display an "edited" note (like here on github).
Allowing revisions to be fetchable would also need changes in the fetch specification, which would make make the implementation for every project more complex.
We could use revision numbers instead of the
This is currently private information and we didn't even store this for very old profiles.
No, we need the timestamp, to prevent that we end up processing an old message, which then would end in the wrong state being stored. You can't edit poll participations or likes (you can delete likes, and preventing processing a like message for an already deleted like is also on my todo-list, but this would need another solution, in our code, not the protocol).
Sure, that makes sense, I'll change that.
Okay, I see. We don't want to support revisions on the protocol level. Looks good to me then.
What if you send a like and then send a dislike for the same post. Isn't it an edit? Do we just ignore it then?
Also since we add editing capabilities to other entities, why then can't we add editing for poll participations and likes then? For poll participations that would make sense to change the poll answer and for likes it would mean changing from like to dislike or vice-a-versa. Having
Diaspora currently doesn't display dislikes, but would receive and relay them. But that wouldn't be an edit (because it has a different GUID) and when you send both, I think the second would fail, because we have a unique index at the
I didn't add anything about polls in this PR (I even marked them as not editable for now in the
But since we are the only one supporting polls (AFAIK?), I think there is no hurry here. So we can discuss the poll related changes another time.
Likes aren't editable, you can delete them and recreate them, but that would be a new entity since it has a new GUID (even dislikes would be a different entity).
Well, what I basically meant is whether we want to allow changing a poll participation from one existing poll answer to another existing poll answer without allowing editing anything else. But in fact we can do it the same way as with likes: retract the original poll participation and push another poll participation as a different entity.
I still don't feel there are any design reasons in making
We currently don't allow deletion of
But for now I just didn't change anything related to polls here (including poll participations), and I think we can discuss all the poll stuff in another discussion, because I think there are maybe more questions or more things we can do (for example maybe the author wants to decide if the people are allowed to change their vote after they created it?). But I just don't want to start this discussion here, so I want to keep the polls as they currently are for the moment.
For me likes aren't editable, the only thing you can do after you created a like is you can delete it. When doing a dislike this isn't a edit to me, this is a new entity, and in theory you can do both at the same time (but the diaspora DB doesn't allow this currently). But since diaspora doesn't allow dislikes we can maybe ask @annando how friendica handles dislikes and if it is possible to have a like and a dislike at the same time or if friendica changes the boolean for the entity with the same guid (if so, we should maybe make likes editable too, but I'm not sure about it)?
Feb 17, 2018
2 checks passed
@cmrd-senya SHIT, I completely forgot to do this before merging :( Sorry (3 weeks are a long time)
But now that I remembered it again and thought about it (if I should do it in a follow up commit), I'm not sure if this is really useful. There is absolutely no "editable behavior" (like in
Do you really think a module is needed here?
Since nobody answered that question... friendica and hubzilla are activitystream based networks and likes and dislikes are activities which have no direct relationship with each other. Many people like and dislike the same post/comment which indicates "ambivalence". We didn't see any need to prevent or block somebody from having mixed feelings. Both activities can be reversed by deleting the underlying activity.