-
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: add explain support for non-cursor commands #2599
feat: add explain support for non-cursor commands #2599
Conversation
58ef4a2
to
35d1814
Compare
d4a3fb2
to
7090c39
Compare
7f19744
to
82f0e60
Compare
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.
LGTM with some nits 👍
src/explain.ts
Outdated
} | ||
|
||
/** Checks that the server supports explain on the given command.*/ | ||
static explainSupportedOnCmd(server: Server, cmd: Document): boolean { |
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.
Could we overload explainSupported
to handle either an op: string
or a cmd: Document
, instead of having two separate methods that are pretty similar in implementation?
if (cmd.explain) { | ||
cmd = decorateWithExplain(cmd, cmd.explain); | ||
} | ||
|
||
server.command( | ||
this.ns.toString(), | ||
cmd, |
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.
This is a stylistic nit, but I think it'd be better to do cmd.explain ? decorateWithExplain(cmd, cmd.explain) : cmd
here rather than reassigning the cmd
parameter.
src/utils.ts
Outdated
delete command.explain; | ||
} | ||
|
||
command = { explain: command, verbosity: explain.verbosity }; |
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'd just return this object literal directly rather than reassigning command
.
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.
lgtm!
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.
A few extra nitpicks.
src/explain.ts
Outdated
import type { Server } from './sdam/server'; | ||
import { maxWireVersion } from './utils'; | ||
|
||
export const Verbosity = { |
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.
Nit: can we expand Verbosity
to ExplainVerbosity
for clarity?
test/functional/explain.test.js
Outdated
return setupDatabase(this.configuration); | ||
}); | ||
|
||
it('shouldHonorBooleanExplainWithDeleteOne', { |
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.
Nit: test names for new tests should be written in normal text with spaces rather than camel case.
src/index.ts
Outdated
@@ -163,6 +163,11 @@ export type { | |||
export type { DbPrivate, DbOptions } from './db'; | |||
export type { AutoEncryptionOptions, AutoEncryptionLoggerLevels, AutoEncrypter } from './deps'; | |||
export type { AnyError, ErrorDescription } from './error'; | |||
export type { | |||
ExplainOptions, | |||
ExplainVerbosity as Verbosity, |
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.
ExplainVerbosity as Verbosity, | |
ExplainVerbosity, |
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.
Oops, not sure how that happened!
src/index.ts
Outdated
export type { | ||
ExplainOptions, | ||
ExplainVerbosity as Verbosity, | ||
ExplainVerbosityLike as VerbosityLike |
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.
ExplainVerbosityLike as VerbosityLike | |
ExplainVerbosityLike |
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.
lgtm
8c5ace7
to
0b37761
Compare
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.
LGTM!
Description
This PR implements
explain
functionality for the relevant non-cursor operations:update
,remove
,distinct
,findAndModify
, andmapReduce
. These operations now accept an additionalexplain
option, either a boolean or a string specifying the requested verbosity, and will be run as explain commands with the specified verbosity.Current syntax:
collection.updateOne(..., {explain: verbosity})
.Other syntax, e.g.:
collection.explain(verbosity).updateOne(...)
is easy to add (or switch to) if we want.What changed?
A new
Explainable
aspect was added so that, inCommandOperation
, operations with that aspect can use theexplain
property already on the class. Logic for validating the explain verbosity passed through the options, adding the explain field to the command, andcanRetryWrite
have been added toCommandOperation
.Not all explainable commands actually call
executeCommand
, includingupdateOne
,deleteOne
, etc. These are handled in the corresponding way: the specified explain verbosity is passed through the options until the command document is created, and then the explain is added to it.Important note: adding an explain to a command alters its shape significantly. For this reason, it should happen at the end of the command building process. This has led to some weirdness where write operations that are being explained still seem like they are doing writes (still call
executeWriteOperation
inserver.ts
). I couldn't see a workaround for this that avoided repeating lots of command building logic. Open to any other suggestions!NODE-2852