[CSHARP-1956] BulkWrite freezes upon writing 0 records Created: 30/Mar/17  Updated: 17/Oct/17  Resolved: 17/Oct/17

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 2.4.3
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Matthew Czarnek Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

I'm finding that when I call collection_name.BulkWrite and pass in a List<WriteModel<>> that has 0 elements in it, BulkWrite will freeze and seems stuck in an infinite loop or something.

Easy enough to fix but considering I was multi-threading this and it was rare for this to occur.. it was a pain to debug.

To be far, it throws an exception I was catching and ignoring But why not just let it write 0 records? And simply don't actually do the write if the List passed in is empty?

Here is a snippet of code that was causing the crash if it helps:

public void StoreXmlDocumentWithCaching(String xmlDoc, int recordNum, bool Failed = false, string BatchDate = "", string queryLocation = "")
        {
            DebuggingHelper.PrintMethodCheckpointMsg(0);
            var filterRecord = Builders<Record>.Filter.Eq("RecordNum", recordNum);
            var updateRecord = Builders<Record>.Update.Set("Document", xmlDoc).Set("BatchDate", BatchDate).Set("Failed", Failed).Set("Sent", false).Set("DeleteMe", false).Set("queryLocation", queryLocation).Set("SendMutex",(int?)null);
 
            try
            {
                UpdateOneModel<Record> updateRecordModel = new UpdateOneModel<Record>(filterRecord, updateRecord) { IsUpsert = true };
 
                cacheMutex.WaitOne();
                    _cacheRecords.Add(updateRecordModel);
                cacheMutex.ReleaseMutex();
            }
            catch (MongoWriteException e)
            {
                Console.WriteLine(e);
            }
            
            cacheMutex.WaitOne();
            docsCached++;
 
            if (docsCached >= numDocsToCache)
            {
                //Send all the cached updates at once.
                _recordCollection.BulkWrite(_cacheRecords);
                //And reset docsCached
                _cacheRecords.Clear();
                docsCached = 0;
            }
            cacheMutex.ReleaseMutex();
            DebuggingHelper.PrintMethodCheckpointMsg(1);
        }
 
        public void FlushStoreXmlCache()
        {
            DebuggingHelper.PrintMethodCheckpointMsg(0);
            cacheMutex.WaitOne();
 
            //write the remaining
            _recordCollection.BulkWrite(_cacheRecords);   <- this line freezes the thread for many hours
 
            //And reset cached docs
            _cacheRecords.Clear();
            docsCached = 0;
 
            cacheMutex.ReleaseMutex();
            DebuggingHelper.PrintMethodCheckpointMsg(1);
        }



 Comments   
Comment by Robert Stam [ 06/Apr/17 ]

I don't know the data type of your _cacheRecords variable, but BulkWrite receives it as an IEnumerable<WriteModel<TDocument>>.

Internally BulkWrite has to enumerate the requests variable, which results in indirectly calling GetEnumerator to get an enumerator, and then calling MoveNext to determine if there are any more items in the sequence. It is possible that the call to MoveNext is the one that is blocking for hours.

Also, there is an open issue regarding that BulkWrite enumerates the requests sequence more than once. Depending on how that sequence is implemented, the multiple enumeration may or may not result in a problem. See CSHARP-1378.

Comment by Robert Stam [ 06/Apr/17 ]

It is considered an error to call BulkWrite with an empty list of requests, and BulkWrite will throw an exception if it is called with an empty list.

Consider the following test:

var requests = Enumerable.Empty<WriteModel<C>>();
collection.BulkWrite(requests);

It throws the following exception immediately:

System.ArgumentException: Must contain at least 1 request.
Parameter name: requests
   at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 151
   at TestCSharp1956.Program.Main(String[] args) in C:\projects\TestCSharp1956\TestCSharp1956\Program.cs:line 27

Generated at Wed Feb 07 21:41:11 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.