CenterForDigitalHumanities / CenterForDigitalHumanities/rerum_server_nodejs
Conflict-Safe Updates
- Vorherrschende Sprache
- JavaScript
- Sterne
- 3
- Forks
- 6
- Ø Merge
- 2 T. 47 Min.
- Gemergte PRs (30 T.)
- 4
Beschreibung
We have had this conversation in the past, but it was rehashed when trying to explain how /update works. For the purposes of this issue, assume you only have control over RERUM API.
The object being updated is...
```Javascript
let orig = {
"@id":"http://devstore.rerum.io/v1/id/123123123123",
"type" : "Message",
"good-bye" : "moon",
"__rerum" : {...}
}
```
it so happens a client did the following
```Javascript
orig.label = "Good Morning!"
```
Then
```Javascript
let updated_orig = await fetch(UPDATE_URL, {
method: 'PUT',
body: JSON.stringify(orig),
headers: new Headers({
'Content-Type': 'application/json; charset=utf-8'
})
}).then(resp => resp.json())
```
Upon success, updated_orig in the client now the following
```JSON
{
"@id":"http://devstore.rerum.io/v1/id/aaaeeeaaaeeeaaeae",
"type" : "Message",
"good-bye" : "moon",
"label" : "Good Morning!",
"__rerum" : {history.previous : "http://devstore.rerum.io/v1/id/123123123123"}
}
```
Let's assume this client user has two devices that had both pulled up `http://devstore.rerum.io/v1/id/123123123123` at the same time. Let's assume they did this action on Device A. Let's assume a session timeout of 20 minutes.
When the user was done on Device A, they picked up Device B and went to refill their coffee. They had an AHA! moment by the coffee pot, so on Device B they updated `http://devstore.rerum.io/v1/id/123123123123` again. This generated a
```JSON
{
"@id":"http://devstore.rerum.io/v1/id/bbbbcccbcbcbccccbc",
"type" : "Message",
"good-bye" : "moon",
"label" : "Good Morning!",
"aha" : "moment,
"__rerum" : {history.previous : "http://devstore.rerum.io/v1/id/123123123123"}
}
```
When getting back to their computer and refreshing the page, they never see this new data node. The only thing that keeps showing up is
```JSON
{
"@id":"http://devstore.rerum.io/v1/id/aaaeeeaaaeeeaaeae",
"type" : "Message",
"good-bye" : "moon",
"label" : "Good Morning!",
"__rerum" : {history.previous : "http://devstore.rerum.io/v1/id/123123123123"}
}
```
This is because `/query` for `{"type":"Message", "__rerum.history.next" : { "$exists": true, "$size": 0 }}` gives the client script http://devstore.rerum.io/v1/id/aaaeeeaaaeeeaaeae **_AND_** http://devstore.rerum.io/v1/id/bbbbcccbcbcbccccbc. The client script NEVER intended to make "conflicts" and so is arbitrarily picking Leaf in History to show. The client cannot /update their way out of this scenario. It has to identify the conflicting node and delete it.
It is likely the client will never know what to do to fix this, and so the user contacts us about seeing the wrong data. Every time this happens.
Note that `/overwrite` is not the solution, as for this same use case it would always show the most recent /overwrite, which in this scenario could still be wrong but easy to /overwrite your way out of.
Suggested RERUM API "Conflict Safe" update
When you go to /update, first get the MongoDB Object with `_id:123123123123`. If it has `__rerum.history.next`, the conflict safe update should return a RESTful code and message about how this would create a conflict. The client can then react how they want-- get confirmation about the conflict then and have a UI for conflict resolution, or force a page refresh to make sure they have the most recent data.
However, note how this affects collaborative working scenarios, like two people working on the same transcription for the same Canvas/Image in the same Project at the same time. We would need RERUM Sockets to allow this collaboration.
Should `v1` have a conflict safe /update available, and should it be the PUT /update by default?
Beitragsleitfaden
Rechercherichtung
Beginne beim PUT /update-Einstiegspunkt und untersuche, wie das MongoDB-Objekt und __rerum.history.next behandelt werden; vergleiche dies mit dem im Issue beschriebenen Verhalten von /query und /overwrite. Lege fest, wie eine Konfliktantwort funktionieren soll und ob konfliktssicheres Verhalten standardmäßig aktiviert ist, und überprüfe anschließend, dass Clients einen Konflikt erkennen können, bevor sie einen weiteren History-Leaf erstellen.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- javascript, mongodb
- Bereich
- api, backend, backend-api-design
- Issue-Typ
- Feature
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Muss geklärt werden
- Anfängerfreundlichkeit
- 25/100