Hello --
At work we are trying out DocumentDB and I believe I have found a race condition involving arrays and the $push operator.
I've made a simplified example in the form of the following shell script (note that it relies on https://www.gnu.org/software/parallel/):
mongoExec () {
cmd="mongo <CONNECTION CONFIG REDACTED> --quiet --eval $1"
$cmd
}
pushElem () {
mongoExec "db.arrayTest.update({id:'test_id',array:{\$not:{\$elemMatch:{name:'$1'}}}},{\$push:{array:{name:'$1'}}})" > /dev/null
}
export -f pushElem mongoExec
mongoExec "db.createCollection('arrayTest')" > /dev/null
mongoExec "db.arrayTest.insert({id:'test_id',array:[]})" > /dev/null
parallel --jobs 9 pushElem ::: A A A B B B C C C
result=`mongoExec "db.arrayTest.find({id:'test_id'})"`
echo $result
mongoExec "db.arrayTest.drop()" > /dev/null
if [ `echo $result | grep -o name | wc -l | xargs` -ne 3 ]
then
exit 1
fi
The script creates a collection arrayTest and inserts the following document containing an empty array:
{
"id": "test_id",
"array": []
}
It then attempts to conditionally push an element to the array inside that document, using the following query, in parallel 9 times -- 3 times each with A, B, and C in place of $1:
db.arrayTest.update(
{id:'test_id', array:{$not:{$elemMatch:{name:'$1'}}}},
{$push:{array:{name:'$1'}}}
)
At the end, it prints out the final state of the document. An example of a successful result (the order of the array entries is irrelevant):
{ "_id" : ObjectId("5c895f5053527cc28b122451"), "id" : "test_id", "array" : [ { "name" : "B" }, { "name" : "C" }, { "name" : "A" } ] }
An example of an unsuccessful result:
{ "_id" : ObjectId("5c89616a4470486421678fa7"), "id" : "test_id", "array" : [ { "name" : "A" }, { "name" : "B" }, { "name" : "B" }, { "name" : "C" } ] }
We've found that, in practice, we're seeing successes about half of the time (in batches of a few hundred runs). Running the same script against the Docker image mongo:latest has not yet ever failed.
Please let me know if you need any more info. Thanks so much for looking into this!