kinto.js
kinto.js copied to clipboard
Prevent concurrent conflicting transactions by incrementing a local revision number
Use case
- We have an edition form for a given record in state A, and we don't have submitted the form yet;
- Concurrently, a worker modifies this record and turns it into state B;
- We now submit the form, which overrides what's just been updated by the worker, which is the problem we're trying to solve here.
Flow
- Form loads existing record with
local_rev==1(eg. that value is contained in some hiddeninputfield, CSRF-token protection style or any other way, eg in React component's props); - Worker loads existing record with
local_rev==1; - Worker updates existing record, persistence layer bumps local_rev to
2; - Form is submitted, data are sent to the local persistence layer adapter;
- Persistence layer knows that local_rev for that record is
2, but form has just sent local_rev==1: an error is raised.
Notes
- Do not synchronize the local revision number to the server;
- Each time we synchronize a remote record from the server to the local database, we reset its local revision number;
- Any synchronized remote records should bump matching local equivalent record's
local_revnumber.
We'd love hearing thoughts and feedback from @daleharvey, @leplatrem, @Natim, @michielbdejong
Makes sense! Already needed for when a user has the same app open in multiple browser tabs, but becomes even more important when using workers. It's a pity that IndexedDB (unlike localStorage) doesn't implement something like StorageEvent, which would have been ideal for this, since it also gives a way to update the UI as soon as a worker (or other browser tab) changes something. In the absence of that, local revision numbers seem like a good second option.