Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update on Dict object results in non-concurrent safe Mongo update #348

Open
Bernie opened this issue Apr 18, 2021 · 3 comments
Open

Update on Dict object results in non-concurrent safe Mongo update #348

Bernie opened this issue Apr 18, 2021 · 3 comments

Comments

@Bernie
Copy link

Bernie commented Apr 18, 2021

If one intends to update a Dict object on a umongo Model by adding or removing an entry in the model, it should be done by a setting/unsetting the Dict elements to avoid issues related to concurrent document updates.

However, umongo instead treats the dict naively, simply setting the entire dict as a whole:

from umongo import Document, fields
from umongo.frameworks import MongoMockInstance
from mongomock import MongoClient
instance = MongoMockInstance(MongoClient().test)

@instance.register
class TestWithDict(Document):
    model_dict = fields.DictField(fields.StringField(), fields.StringField())

test = TestWithDict(model_dict={})
test.commit()

test = TestWithDict.find_one()

test.model_dict['my_key'] = 'my_val'
test.to_mongo(update=True)

The end result of the update query is:

{'$set': {'model_dict': {'my_key': 'my_val'}}}

Which unfortunately is not concurrent safe. If another process had made an update on the dict between this fetch and update, the other update would be erased.

A safer update operation would be:

{'$set': {'model_dict.my_key': 'my_val'}}

This type of update enables a safe merging of the model's view with what is existing in the DB even when an outside update was made in between the fetch and update, and should be preferred.

@Neustradamus

This comment has been minimized.

@lafrech
Copy link
Collaborator

lafrech commented Apr 22, 2021

@Bernie, I'm not sure we can even try to support this.

The issue is the same with embedded documents and lists, isn't it?

Only the first document level generates '$set' and such. For all nested levels, the whole substructure is erased.

Not saying it is a good thing, but that's how it is right now, the Dict behaviour is not an exception, and changing this would be a huge change. Besides, I'm not sure concurrent safety can be achieved. Even if we managed to yield a correct atomic change, there would be corner cases where one change makes the other obsolete (like if the first change removes the whole substructure).

@Neustradamus

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants