At some point between 2.6 and 2.17, the Ruby driver began associating an operation's limit as the batchSize for a getMore command. For example:
require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'mongo', '2.6.2' # uncomment below and comment out above to use 2.17.1 instead #gem 'mongo', '2.17.1' end client = Mongo::Client.new('mongodb://localhost:27017/test') collection = client[:foo] collection.drop collection.insert_many([].fill({ "bar": "baz" }, 0, 102)) Mongo::Logger.logger.level = Logger::DEBUG collection.find({bar: "baz"}, { limit: 0 }).to_a.size rescue nil
When the above is run using 2.6.2 the output from command monitor will be:
D, [2022-06-13T15:55:27.733672 #45047] DEBUG -- : MONGODB | localhost:27017 | test.getMore | STARTED | {"getMore"=>5932819205641482470, "collection"=>"foo", "lsid"=>{"id"=><BSON::Binary:0x1320 type=uuid data=0x1fe355952b144c09...>}} D, [2022-06-13T15:55:27.734129 #45047] DEBUG -- : MONGODB | localhost:27017 | test.getMore | SUCCEEDED | 0.000s
Running the same code wiht the 2.17.1 driver will fail, showing the batchSize having been set to 0:
D, [2022-06-13T15:54:51.772890 #44733] DEBUG -- : MONGODB | localhost:27017 req:8 conn:1:1 sconn:11 | test.getMore | STARTED | {"getMore"=>#<BSON::Int64:0x00007f87b6159d80 @value=7618985499189845324>, "collection"=>"foo", "batchSize"=>0, "$db"=>"test", "lsid"=>{"id"=><BSON::Binary:0x1420 type=uuid data=0xa8480abeaa674f4a...>}} D, [2022-06-13T15:54:51.773331 #44733] DEBUG -- : MONGODB | localhost:27017 req:8 | test.getMore | FAILED | [2:BadValue]: Batch size for getMore must be positive, but received: 0 | 0.00031999999191612005s
Further instrumenting the code to use TracePoints shows the builder implementations changed significantly between these versions:
require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'mongo', '2.6.2' #gem 'mongo', '2.17.1' end client = Mongo::Client.new('mongodb://localhost:27017/test') collection = client[:foo] collection.drop collection.insert_many([].fill({ "bar": "baz" }, 0, 102)) def with_tracepoint trace = [] tp = TracePoint.new(:call) do |x| trace << "#{x.defined_class}##{x.method_id.to_s} @ #{x.path}" end tp.enable yield return trace ensure tp.disable unless tp.nil? end Mongo::Logger.logger.level = Logger::INFO puts with_tracepoint { collection.find({bar: "baz"}, { limit: 0 }).to_a.size rescue nil }
The getMore initialization changes from Mongo::Cursor::Builder::GetMoreCommand#initialize to Mongo::Operation::GetMore::CommandBuilder#selector, and the logic for converting limit and batch size moves from Mongo::Collection::View::Builder::FindCommand#convert_limit_and_batch_size to #<Class:Mongo::Operation::Find::Builder::Command>#convert_limit_and_batch_size!
Was there a regression in the getMore builder as a result of an overhaul to the builders at some point?