-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(NODE-6136): parse cursor responses on demand #4112
base: main
Are you sure you want to change the base?
Conversation
df69639
to
e6de40a
Compare
31efa9c
to
a37ec31
Compare
a37ec31
to
be871b8
Compare
src/cmap/connection.ts
Outdated
ns, | ||
encrypted, | ||
options, | ||
(responseType ?? MongoDBResponse) as any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come casting is necessary here? I'd expect responseType ?? MongoDBResponse to produce a type of MongoDBResponse
, which should satisfy super.command()'s types without casting, and should produce the correct return type without as unknown as MongoDBResponse
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, I'm committing type crimes. I added a comment clarifying this, but it is not right that we are saying command
of T
and then passing in MongoDBResponse
when responseType is nullish because now that may not match T
. I can move to the type crime into the generic or here on the argument, but it will exist until we can only pass in a responseType
without defaulting to a different subtype constraint.
typeof MongoDBResponse' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'MongoDBResponseConstructor'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we remove the generic on super
? then super.command() should resolve to a mongodbresponse instance.
If there is no response type provided, line 777 resolves to a plain document of type T. So there wouldn't be TS issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I got it, TY, needed a non-nullish overload on the superclass otherwise this was still saying the result could be Document
. Fixed!
@@ -13,7 +13,7 @@ export interface CountDocumentsOptions extends AggregateOptions { | |||
} | |||
|
|||
/** @internal */ | |||
export class CountDocumentsOperation extends AggregateOperation<number> { | |||
export class CountDocumentsOperation extends AggregateOperation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export class CountDocumentsOperation extends AggregateOperation { | |
export class CountDocumentsOperation extends AggregateOperation<number> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AggregateOperation
is not generic and if it were it can't be that a subclass returns an incompatible type from the parent. (ex. Parent -> A -> B, B cannot have a method incompatible with Parent otherwise things that expect "Parent" will break when given Bs) This and the command below are TODO_NODE_3286
related. The operations layer TS does not work well and here in particular because the expectation (and reality) is that every command returns an object, I think returning a "number" should be handled up in the coll.countDocument
API. Taking it even further I don't see the value in this subclass? can we just call this.aggregate
from within collection.countDocuments
?
Stuck the appropriate type annotation on here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, agreed - the preferable approach would be to remove this class entirely (up to you). We do have this precedent with our index management APIs too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description
What is changing?
ok === 0
)makeWriteConcernResultObject
would delete properties when ok was set to 0 which is never the case for a writeConcernError because the "command succeeded" the "write concern/requirements failed". The delete logic would not run and the unit tests that asserted the properties did not exist only passed because the mock data fed in was inaccurate.writeConcernError
property.Is there new documentation needed for these changes?
No.
What is the motivation for this change?
Performance and enhancing internal capabilities for discrete BSON parsing.
Release Highlight
Cursor responses are now parsed lazily 🦥
MongoDB cursors (find, aggregate, etc.) operate on batches of documents equal to
batchSize
. Each time the driver runs out of documents for the current batch it gets more (getMore
) and returns each document one at a time through APIs likecursor.next()
orfor await (const doc of cursor)
.Prior to this change, the Node.js driver was designed in such a way that the entire BSON response was decoded after it was received. Parsing BSON, just like parsing JSON, is a synchronous blocking operation. This means that throughout a cursor's lifetime invocations of
.next()
that need to fetch a new batch hold up on parsingbatchSize
(default 1000) documents before returning to the user.In an effort to provide more responsiveness, the driver now decodes BSON "on demand". By operating on the layers of data returned by the server, the driver now receives a batch, and only obtains metadata like size, and if there are more documents to iterate after this batch. After that, each document is parsed out of the BSON as the cursor is iterated.
A perfect example of where this comes in handy is our beloved
mongosh
! 💚That
Type "it" for more
message would now print after parsing only the documents displayed rather than after the entire batch is parsed.Double check the following
npm run check:lint
scripttype(NODE-xxxx)[!]: description
feat(NODE-1234)!: rewriting everything in coffeescript