mongodb/mongo-ruby-driver — pull request #326 by gjmurakami-10gen (2013-12-05 00:44:22+00:00)
Title: bulk API comprehensive return value or exception - errors and exchanges

This is a comprehensive and coherent strategy and implementation for return value or exception for bulk API operations. The main methods BulkWriteCollectionView#execute and CollectionWriter#batch_write_incremental collect exchanges and errors during bulk processing. An exchange is a DB request (bulk-API request parameters)/response, including a response for a request that raised and exception, so exchanges cover all DB operations. An error is any OperationFailure or BSON exception. If the bulk request succeeds without error, exchanges are returned. If there is an error, a BulkWriteError exception is raised and the "result" member encapsulates both the errors and the exchanges. So for successful execution, the user can examine any batch DB request and paired response. If an error occurs, the user can examine the errors and also inspect the exchanges for partial results. A BSON error is wrapped in a BulkWriteError to encapsulate details for a failed serialization.

All of this only takes about a dozen lines to implement. I think that it is simpler and saner than the merge and reordering specified in the spec, and that it preserves both the exchange request/response pairing and any bulk execution splitting into batches. I will continue to spike out the spec with merge mess, but I think that this is functionally complete and superior, and I'd like to merge this pull request as a standard that must be exceeded.

- example return value
[{:op=>:insert,
:batch=>
[{:a=>1, :_id=>BSON::ObjectId('529fa2157f11ba579b000001')},
{:a=>2, :_id=>BSON::ObjectId('529fa2157f11ba579b000002')},
{:a=>3, :_id=>BSON::ObjectId('529fa2157f11ba579b000003')},
{:a=>4, :_id=>BSON::ObjectId('529fa2157f11ba579b000004')},
{:a=>5, :_id=>BSON::ObjectId('529fa2157f11ba579b000005')}],
:opts=>{:w=>1, :j=>1, :ordered=>true},
:response=>{"ok"=>1, "n"=>5}},
{:op=>:update,
:batch=>
[{:q=>{:a=>1}, :u=>{"$inc"=>{:x=>1}}, :multi=>false},
{:q=>{:a=>2}, :u=>{"$inc"=>{:x=>2}}, :multi=>true},
{:q=>{:a=>3}, :u=>{:x=>3}, :multi=>false},
{:q=>{:a=>1}, :upsert=>true, :u=>{"$inc"=>{:x=>1}}, :multi=>false},
{:q=>{:a=>2}, :upsert=>true, :u=>{"$inc"=>{:x=>2}}, :multi=>true},
{:q=>{:a=>3}, :upsert=>true, :u=>{:x=>3}, :multi=>false}],
:opts=>{:w=>1, :j=>1, :ordered=>true},
:response=>
{"ok"=>1,
"n"=>6,
"upserted"=>
[{"index"=>5, "_id"=>BSON::ObjectId('529fa215f6785aed244c129e')}]}},
{:op=>:delete,
:batch=>
[{:q=>{:a=>4}, :upsert=>true, :limit=>1},
{:q=>{:a=>5}, :upsert=>true, :limit=>0}],
:opts=>{:w=>1, :j=>1, :ordered=>true},
:response=>{"ok"=>1, "n"=>2}},
{:op=>:insert,
:batch=>[{:x=>4, :_id=>BSON::ObjectId('529fa2157f11ba579b000006')}],
:opts=>{:w=>1, :j=>1, :ordered=>true},
:response=>{"ok"=>1, "n"=>1}}]

- example exception
#1, "code"=>11000, "errmsg"=>"E11000 duplicate key error index: bulk_write_collection_view_test.test.$_id_ dup key: { : 1 }"}]'). - examine result for complete information>

- example exception result
{:errors=>
[#,
#1, "code"=>11000, "errmsg"=>"E11000 duplicate key error index: bulk_write_collection_view_test.test.$_id_ dup key: { : 1 }"}]').>],
:exchanges=>
[{:op=>:insert,
:batch=>[{:_id=>1, :a=>1}, {:_id=>1, :a=>2}, {:_id=>3, :a=>3}],
:opts=>{:ordered=>false},
:response=>
{"ok"=>0,
"code"=>65,
"errmsg"=>"batch op errors occurred",
"n"=>2,
"errDetails"=>
[{"index"=>1,
"code"=>11000,
"errmsg"=>
"E11000 duplicate key error index: bulk_write_collection_view_test.test.$_id_ dup key: { : 1 }"}]}}]}

- example exception result BSON error result
{:op=>:insert,
:serialize=>
{"_id"=>BSON::ObjectId('529fc94ba3f5766e0d000018'),
"x"=>
"yyy...yyy"},
:error=>
#}

- example exception result DB error result
{"ok"=>0,
"code"=>65,
"errmsg"=>"batch op errors occurred",
"n"=>2,
"errDetails"=>
[{"index"=>1,
"code"=>11000,
"errmsg"=>
"E11000 duplicate key error index: bulk_write_collection_view_test.test.$_id_ dup key: { : 1 }"}]}