{"action":"created","issue":{"url":"https://api.github.com/repos/MongoEngine/mongoengine/issues/854","labels_url":"https://api.github.com/repos/MongoEngine/mongoengine/issues/854/labels{/name}","comments_url":"https://api.github.com/repos/MongoEngine/mongoengine/issues/854/comments","events_url":"https://api.github.com/repos/MongoEngine/mongoengine/issues/854/events","html_url":"https://github.com/MongoEngine/mongoengine/issues/854","id":54800107,"number":854,"title":".save() updates only first-level dirty fields","user":{"login":"snario","id":1933029,"avatar_url":"https://avatars.githubusercontent.com/u/1933029?v=3","gravatar_id":"","url":"https://api.github.com/users/snario","html_url":"https://github.com/snario","followers_url":"https://api.github.com/users/snario/followers","following_url":"https://api.github.com/users/snario/following{/other_user}","gists_url":"https://api.github.com/users/snario/gists{/gist_id}","starred_url":"https://api.github.com/users/snario/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/snario/subscriptions","organizations_url":"https://api.github.com/users/snario/orgs","repos_url":"https://api.github.com/users/snario/repos","events_url":"https://api.github.com/users/snario/events{/privacy}","received_events_url":"https://api.github.com/users/snario/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-01-19T19:00:11Z","updated_at":"2015-01-20T16:50:16Z","closed_at":null,"body":"Say I have a document like:\r\n\r\n`{A: {a: \"one\", b: \"two\"}}`\r\n\r\nand then it is modelled using MongoEngine as some variable `X` and I say:\r\n\r\n`X.a = \"new-one\"`\r\n\r\nthen when I do `X.save()`, MongoEngine will _overwrite_ `X.b = \"two\"` as well. This means that if I have two threads changing the document at the same time, one changing `X.a` and the other changing `X.b`, then this will cause data inconsistency.\r\n\r\nThe fix is to ensure that `.save()` checks for dirtiness _recursively_ and not just on the first level of the structure."},"comment":{"url":"https://api.github.com/repos/MongoEngine/mongoengine/issues/comments/70688150","html_url":"https://github.com/MongoEngine/mongoengine/issues/854#issuecomment-70688150","issue_url":"https://api.github.com/repos/MongoEngine/mongoengine/issues/854","id":70688150,"user":{"login":"xLegoz","id":1161183,"avatar_url":"https://avatars.githubusercontent.com/u/1161183?v=3","gravatar_id":"","url":"https://api.github.com/users/xLegoz","html_url":"https://github.com/xLegoz","followers_url":"https://api.github.com/users/xLegoz/followers","following_url":"https://api.github.com/users/xLegoz/following{/other_user}","gists_url":"https://api.github.com/users/xLegoz/gists{/gist_id}","starred_url":"https://api.github.com/users/xLegoz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xLegoz/subscriptions","organizations_url":"https://api.github.com/users/xLegoz/orgs","repos_url":"https://api.github.com/users/xLegoz/repos","events_url":"https://api.github.com/users/xLegoz/events{/privacy}","received_events_url":"https://api.github.com/users/xLegoz/received_events","type":"User","site_admin":false},"created_at":"2015-01-20T16:50:15Z","updated_at":"2015-01-20T16:50:15Z","body":"I will look into it further as there were a few more specific details about the use and I will try to create a test to reproduce it when I narrow it down.\r\n\r\nSome more details about it:\r\n- It was on a DictField on the Document.\r\n- The values of the dict fields were a large JSON structure or a large string representing the JSON. Both were tested and had the same issue during development.\r\n\r\nThe timeline looked something like this, with instance A and B being on two different processes.\r\n```python\r\nA = Document.objects().first()\r\nB = Document.objects().first()\r\nA.data['key'] = value # about 4 seconds later\r\nA.save()\r\nB.data['key'] = value # another 4 seconds later\r\nB.save()\r\n```\r\n"}}