I’m working with MongoDB on my current project and a little confused about the proper way to build support for concurrent modifications.
I have an array of objects. When a request comes in, I want to inspect the last element in that array and make a conditional decision on how to respond. My code looks something like the following:
# Find the last object ID in the array.
last_element_id = str(document['objects'][-1])
if last_element_id != the_element_id_the_request_is_responding_to:
db.documents.insert({
...
})
else:
# Append the response to the end of the array.
document['objects'].append(new_element_id)
db.documents.save(document)
I’m concerned about the situation in which:
- In handling request A, I find the last_element_id is valid, and
the response should be appended to the end of the list. - Before
the append() and save() operations complete, another request, B, is
handled. - B also sees the last_element_id is valid, appends() the
response and saves(). - Now, A’s response is enqueued into the end
of the array, but the response no longer follows the supposed
‘last_element_id’ since B’s response snuck in beforehand.
What is the proper way to handle this kind of logic in Mongo’s atomicity model? I don’t want to employ locks if I can avoid them, since the WSGI application may be run in multiple processes simultaneously.
Thanks!
You can use optimistic locking..,, one way is to add a field called version to the document and then increment it on every update, and when you update make sure that the version in the document is the same as the one you read in.
I could give more detail, but this is fairly well documented at http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22
Let me know if this works for you,