Structured Content 2022: Join our conference to explore fresh perspectives on content and digital experiences →

it looks like our problems are caused by editors publishing drafts after backend token has updated docs, and thus overwriting it

20 replies
Last updated: Sep 10, 2020

Hi, we have a problem with drafts. By using the history api trying to make sense of that happens, it looks like our problems are caused by editors publishing drafts after backend token has updated docs, and thus overwriting it. Here’s what I think is going on:1. An editor starts editing a document, could be by accident, and then forgets to publish it.
2. Our server updates the document one or more times
3. Some editor that comes across the doc, publishes the draft.
It looks like this process
causes us to loose all the patches from step 2. And the time from 1-3 may be a few seconds (not likely for anything to happen at step 2), or days (more likely that our server did some work at step 2).
• I could encourage all editors to discard all drafts that they come across, and don’t publish anything that they haven’t edited the last few seconds.
This should keep the changes from step 2, right?• If editors are encouraged to keep drafts open only for a short period of time before publishing, the probability of something else being written to the doc in the meantime is very low. However, there’s still a small chance that step 2 will happen even though an editor is working with the doc only for a second or two, before publishing.
So what’s how do we prevent editors from overwriting updates our backend did?

Sep 9, 2020, 10:09 AM

Hi Stian, this is an interesting question. The use case is valid but unfortunately it’s also a limitation of our draft model. Inside the Studio, it won’t allow you to edit the original so this issue would not occur. However, as you suggest, this is not the case for external mutations.
Rather than asking editors to tiptoe around the Studio and avoid using drafts (thereby limiting their workflow), I would suggest trying to fix this on the server side instead. Nevertheless, there is a document property called

liveEdit
that disables drafts altogether if you prefer to take that route.
Regarding the server patches, are these changes to fields editable by users or rather `readOnly`/`hidden` fields? You could consider checking for the existence of a draft version and, if so, patch both the draft and the non-draft document. This would go around the issue even if editors subsequently publish or discard the draft. However, it could lead to unexpected results if it changes fields that editors thought to have updated in the draft - hence the question on these fields being shielded
🙂

Sep 9, 2020, 11:21 AM

Quick question first; there can only be one draft for each document, right? And if more than one editor is editing the document at the same time, they are editing the same draft?
So the server patches change all kinds of fields, hidden, read only, etc. And what happens is that the editor publishing a draft will ignore the changes on the backend “branch” of changes. So as long as a document is opened for editing, all backend changes will be overwritten when it’s published, and kept if Studio changes are discarded. That’s at least what it looks like.

I think our best option is to try

liveEdit
. Because I don’t really want to deal with the complexity of having to update multiple documents… To us that would be supporting an edge case. It’s better to drop the idea of drafts.

Sep 9, 2020, 11:40 AM

But I need to think through what happens if editors update documents with invalid data. I guess that if the input does not pass validation, the patch will be rejected? It’s more a question of can I / will I be able to write correct and up to date validation functions for all fields.

Sep 9, 2020, 11:41 AM

Hmm, looks like when using

liveEdit: true
, the document is saved even though it does not pass validation…. If that’s the case, we cannot use live edit

Sep 9, 2020, 11:57 AM

Indeed, there’s only one draft (when there’s a draft). And the behaviour you describe makes sense. The draft is created from the original and then the original is changed by the server patches, so the draft being published overwrites those changes to the original.
Patching both the original and the draft version could mitigate this, but that might also overwrite changes an editor had in mind for a (not hidden/read-only) field.

Regarding your pre-last comment, if you set up validation in the Studio this should prevent editors from publishing invalid input. If you’re referring to editors being able to push server patches outside of the Studio, then you’d have to take care of validation on that side as well.

Let me check the

liveEdit
validation issue - that’s unexpected indeed.

Sep 9, 2020, 11:58 AM

Looks like we cannot browse history in live edit mode either. But I’m going to merge a branch where we updated to the newest version of Sanity. We may be a bit behind

Sep 9, 2020, 12:02 PM

Updated to newest version, and live mode still writes invalid input

Sep 9, 2020, 12:32 PM

Ok, so our solution for now will be to ask all editors to discard drafts they come across and haven’t worked with the last minute or so. We usually do pretty small changes, so a minute should be sufficient. Then a conflict is at least less likely.
And, also I will write a cron job that spams our general channel with open drafts…

My biggest wish from you guys right now is a way to let editors know that the document has a newer revision set by some other user = backend token during edit. Then they could stop editing, and start from the newest version.

Sep 9, 2020, 2:23 PM

That last part is probably something that can be achieved using custom document actions: e.g. on publish run a check for the time the draft document was created (query history API for example) and compare it to the

_updatedAt
of the original doc. If the latter is more recent, there have been changes and you could not publish but show an alert instead.

Sep 9, 2020, 2:38 PM

Hmm, what are custom document actions? Documented somewhere, or do I have to write my own publish component?

Sep 9, 2020, 2:42 PM
Sep 9, 2020, 2:43 PM

Yeah, found it. I’ll look into it

Sep 9, 2020, 2:43 PM

Thanks

Sep 9, 2020, 2:43 PM

Looks like

props.draft._createdAt
is when the original doc was created. And
props.draft._updatedAt
will update when the draft changes, so the draft will always be fresher than the original (Unless it’s an old draft, but input one character and it’s fresher). You mentioned the history API, will I get other value for the draft’s
_createdAt
there?

Sep 9, 2020, 3:45 PM

Looks like I won’t get unpublished drafts from the history API anyways

Sep 9, 2020, 3:49 PM

Nevermind, if I get the draft’s history I get the last draft’s timestamp

/transactions/drafts.<id>

Sep 9, 2020, 3:54 PM

It kinda sucks that I have to visit the history API to figure out if I can publish a doc or not. It would have been super helpful if this was something that came out of the box.
I’ll implement a solution because we really need this. If it’s a quick fix, providing the draft creation time in document actions props will save people a lot of pulling in axios, leaving a token there (cause you can’t get history from the client, right?) and dealing with ndjson.

Sep 9, 2020, 4:13 PM

Indeed, getting draft creation directly makes a lot of sense for this use case. Also, having an option to patch drafts automatically, similar to

createIfNotExists
on the mutation API, would be useful here. Thanks for the feedback in this thread Stian. I’ll make sure to forward this to the people involved in projects related to the above.
However, I guess the good news is that despite the need to go around this stuff it seems like we have a way to alert editors in case changes happened while they were editing a document. I hope in the future we’ll be able to offer some more functionality around this, perhaps even going around the need for custom actions.

Sep 9, 2020, 4:17 PM

yeah, hope so too! Thanks for all help!

Sep 9, 2020, 4:23 PM

Hmm, I don’t know about this. It seems that the request to history api is not guaranteed to get the current draft, so I would have to set a delay for a second or so. Also, after visiting the original PublishAction component (https://github.com/sanity-io/sanity/blob/fae42f5e0b5f09e725a3fbdde6ed1580b3a98d67/packages/%40sanity/desk-tool/src/actions/PublishAction.tsx ), I noticed that there is actually a lot of useful logic going on there, like validation. It’s a 113 lines long, quite messy, file and copying it and adding revision checks would make it even more messy, and I would have to make sure my altered component and the original one has the same base functionality when upgrading sanity.
I really feel this is core revision functionality and you should not let editors overwrite more recent versions of the same document.

It would be way more solid if you solved this on your end. A custom component written by someone who does not know the intention behind the original PublishAction, will deviate from the intended functionality over time, get outdated on upgrades and probably introduce bugs.

Are you planning on fixing the drafts model any time soon? It should be aware of other branches of the same document, and show conflict to editors if necessary, not just overwrite data.

Sep 10, 2020, 9:25 AM

Sanity.io: Get the most out of your content

Sanity.io is a platform to build websites and applications. It comes with great APIs that let you treat content like data. Give your team exactly what they need to edit and publish their content with the customizable Sanity Studio. Get real-time collaboration out of the box. Sanity.io comes with a hosted datastore for JSON documents, query languages like GROQ and GraphQL, CDNs, on-demand asset transformations, presentation agnostic rich text, plugins, and much more.

Don't compromise on developer experience. Join thousands of developers and trusted companies and power your content with Sanity.io. Free to get started, pay-as-you-go on all plans.