-
Notifications
You must be signed in to change notification settings - Fork 904
GODRIVER-3037 Support internal-only options. #2023
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
base: master
Are you sure you want to change the base?
Conversation
API Change Report./v2/mongo/optionscompatible changesClientOptions.Custom: added ./v2/x/mongo/driver/xoptionscompatible changespackage added |
mongo/options/internaloptions.go
Outdated
// SetInternalClientOptions sets internal options for ClientOptions. | ||
// | ||
// Deprecated: This function is for internal use only. It may be changed or removed in any release. | ||
func SetInternalClientOptions(opts *ClientOptions, custom map[string]any) (*ClientOptions, error) { |
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 this function live in the experimental API? What is the pattern for future custom data? Should ClientOptions be extended with a Custom
field of type map[string]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.
Consider the following pattern:
type ClientOptions struct {
custom map[string]any
}
func WithCustomValue(co ClientOptions, key string, val any) ClientOptions {}
func CustomValue(co ClientOptions key string) any {}
Then in x/mongo/driver:
const someExperimentKey = "x/mongo/driver:myExperiment"
func WithSomeExperimentValue(co options.ClientOptions, on bool) options.ClientOptions {
return options.WithCustomValue(co, someExperimentKey, on)
}
func SomeExperimentValue(co options.ClientOptions) bool {
val := options.CustomValue(co, someExperimentKey)
if b, ok := val.(bool); ok {
return b
}
return false
}
The usage would look something like this:
clientOpts, _ := options.Client()
clientOpts = driver.WithSomeExperimentValue(clientOpts, true)
// ...
And we would check it internally like this:
expVal := driver.SomeExperimentValue(clientOpts)
// ...
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.
Instead of an expressive interface, I'd prefer a map-style interface without any hint other than a user-provided option name to add obfuscation to discourage general users from using it. However, it makes sense to wrap the map[string]any
in a struct and move it to "x/mongo/driver" to emphasize it is "experimental".
I can stack another PR for GODRIVER-3429 (internal-only "AuthenticateToAnything") on top of this one to demonstrate future custom data.
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 this solution is fine for now, we can update if needed later.
// | ||
// Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any | ||
// release. | ||
Custom options.Options |
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.
Will this work if a user sets crypt or deployment with it? Should we update the setter to support both directly setting and using custom? If so, we should update the comments for the Crypt and Deployment fields with the 3.0 removal notice. For example:
// Crypt specifies a custom driver.Crypt to be used to encrypt and decrypt documents. The default is no
// encryption.
//
// Deprecated: This option is for internal use only and should not be set (see GODRIVER-2149). It may be
// changed or removed in any release. This option will be removed in 3.0 and replaced with the Custom
// options.Options pattern: SetInternalClientOptions(client, "crypt", myCrypt)
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 still unresolved.
x/mongo/driver/options/options.go
Outdated
// SetInternalClientOptions sets internal options for ClientOptions. | ||
// | ||
// Deprecated: This function is for internal use only. It may be changed or removed in any release. | ||
func SetInternalClientOptions(opts *options.ClientOptions, key string, option any) error { |
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.
Suggest updating this now to support the custom field and extending the compilecheck to show that it doesn't break anything:
package main
import (
"fmt"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"go.mongodb.org/mongo-driver/v2/x/mongo/driver/options"
)
func main() {
opts := options.Client()
options.SetInternalClientOptions(opts, "foo", "bar")
_, _ = mongo.Connect(options.Client())
fmt.Println(bson.D{{Key: "key", Value: "value"}})
}
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 still unresolved.
x/mongo/driver/options/options.go
Outdated
// not use this file except in compliance with the License. You may obtain | ||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
package options |
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.
Should we name this package something different to avoid import conflicts? Perhaps xoptions?
// SetInternalClientOptions sets internal options for ClientOptions. | ||
// | ||
// Deprecated: This function is for internal use only. It may be changed or removed in any release. | ||
func SetInternalClientOptions(opts *options.ClientOptions, key string, option any) error { |
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.
Do we need this to return an error? Should we just do nothing if an unsupported option is set?
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 prefer to keep the return to avoid silent errors, for example, a typo in the key name. Otherwise, these errors would be difficult to find.
GODRIVER-3037
Summary
Support setting internal-only options with a helper function.
Background & Motivation
This proposal does not change the current interface.
The option names are not publicly exposed to the user, so it is less likely to be used without internal knowledge.
We can add a
map[string]any
namedcustom
inClientOptions
struct for future internal options, such as AuthenticateToAnything.The
Crypt
andDeployment
fields inClientOptions
will be merged into the aforementioned map in v3.