bruvellu / cifonauta

Marine biology image database by CEBIMar/USP
http://cifonauta.cebimar.usp.br
GNU General Public License v3.0
21 stars 5 forks source link

Prevent unexpected data loss from concurrent editing #263

Open bruvellu opened 7 months ago

bruvellu commented 7 months ago

Two users editing the metadata of the same image at the same time can lead to data loss. For example:

  1. Image with title field as “Old title”
  2. User A opens the editing form
  3. User B opens the editing form
  4. User B changes the title field to “New title from B”
  5. User B presses save
  6. User A changes another field without changing the title
  7. User A presses save
  8. Image is saved with the title “Old title” (edit from User B is lost)

Django has the select_for_update method, which blocks DB transactions for specific fields. But this is more of a low-level function to prevent concurrent transactions, when the block is released the waiting transaction is applied. Which in our case would also cause data loss.

bruvellu commented 7 months ago

One solution is to have an is_locked = True/False boolean field in Media. Every time a user opens the editor, is_locked is set to True. If another user tries to edit the same image, it'll get an error saying the image is locked. Once the image is saved by the first user, is_locked is set to False. Now another user can edit the image using the up-to-date metadata.

To update the is_locked field, we should use the query set update() method instead of the model save() to avoid triggering unnecessarily auto-fields like the date_modified timestamp.