-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CSHARP-5560: CSOT: Refactor IOperationExecutor to use operation context #1676
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: main
Are you sure you want to change the base?
Conversation
{ | ||
return operation.Execute(binding, cancellationToken); | ||
bool isOwnSession = session == null; |
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: use var?
here and other methods in this file
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.
Fixed.
{ | ||
return _client.StartImplicitSessionAsync(cancellationToken); | ||
var options = new ClientSessionOptions { CausalConsistency = false, Snapshot = false }; | ||
ICoreSessionHandle coreSession = _client.GetClusterInternal().StartSession(options.ToCore(isImplicit: true)); |
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: use var?
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.
Fixed.
|
||
namespace MongoDB.Driver | ||
{ | ||
internal record class ReadOperationOptions(ReadPreference ExplicitReadPreference = null, ReadPreference DefaultReadPreference = null); |
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.
no need for specifying class
? I believe record
is equivalent to record class
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'm OK with removing the class here. I've left it only to stress on the fact that it should be class, not struct. As changing to struct might affect its functionality (because of the copy-by-value nature of structs).
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 let's remove the class, record is by default a class and if someone tries to change it to struct then we can address it then in the PR containing that change.
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.
Done
return UsingImplicitSession(session => BulkWrite(session, requests, options, cancellationToken), cancellationToken); | ||
using var session = OperationExecutor.StartImplicitSession(cancellationToken); | ||
return BulkWrite(session, requests, options, cancellationToken); |
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 noticed that for some of the other methods above (like AggregateToCollection
) you did not use OperationExecutor
to create the implicit session and just used the existing UsingImplicitSession
mechanism. Should we update all those use cases as well? or am I missing something?
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.
The idea was to hide the implicit session creation inside of the OperationExecutor. But for some corner cases (like Aggregate method) we should have access to the created session, so sometimes we have to create the implicit session from outside.
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.
Thank you for reporting this. I've converted rest of the methods and removed UsingImplicitSession
.
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.
Looks good! left some minor comments
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.
partial review: minor comments so far.
@@ -58,6 +58,8 @@ private MongoCollectionImpl(IMongoDatabase database, CollectionNamespace collect | |||
_documentSerializer = Ensure.IsNotNull(documentSerializer, nameof(documentSerializer)); | |||
|
|||
_messageEncoderSettings = GetMessageEncoderSettings(); | |||
_readOperationOptions = new ReadOperationOptions(DefaultReadPreference: _settings.ReadPreference); | |||
_writeOperationOptions = new WriteOperationOptions(); |
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.
minor:
_readOperationOptions = new()
_writeOperationOptions = new(...)
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.
Done
Ensure.IsNotNullOrEmpty(name, nameof(name)); | ||
if (name == "*") | ||
{ | ||
throw new ArgumentException("Cannot specify '*' for the index name. Use DropAllAsync to drop all indexes.", "name"); |
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.
minor: mistake in the original code, should be DropAll
and DropAllAsync
.
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.
Done
src/MongoDB.Driver/MongoDatabase.cs
Outdated
@@ -50,6 +51,9 @@ public MongoDatabase(IMongoClient client, DatabaseNamespace databaseNamespace, M | |||
_settings = Ensure.IsNotNull(settings, nameof(settings)).Freeze(); | |||
_cluster = Ensure.IsNotNull(cluster, nameof(cluster)); | |||
_operationExecutor = Ensure.IsNotNull(operationExecutor, nameof(operationExecutor)); | |||
|
|||
_readOperationOptions = new ReadOperationOptions(DefaultReadPreference: _settings.ReadPreference); | |||
_writeOperationOptions = new WriteOperationOptions(); |
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.
minor: new(...)
?
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.
Done.
|
||
private IReadWriteBindingHandle CreateReadWriteBinding(IClientSessionHandle session) | ||
{ | ||
// TODO: CreateReadWriteBinding from MongoClient did not used ChannelPinningHelper, double-check if it's OK to start using it |
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.
Need to address this TODO.
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.
Add parameter to disable channel pinning + ticket to investigate why do we need that: https://jira.mongodb.org/browse/CSHARP-5600
src/MongoDB.Driver/MongoClient.cs
Outdated
@@ -100,7 +104,7 @@ public MongoClient(string connectionString) | |||
internal MongoClient(IOperationExecutor operationExecutor, MongoClientSettings settings) | |||
: this(settings) | |||
{ | |||
_operationExecutor = operationExecutor; | |||
_operationExecutor = new OperationExecutorWrapper(operationExecutor); |
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 using the Fork
approach.
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.
@BorisDog what is the Fork
approach?
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.
The problem here is: MongoClient implements IDisposable, and disposed mongo client throws ObjectDisposedException. MongoDatabase and MongoCollection are not disposable on other hand. However most of work regarding commands execution is implemented in OperationExecutor, that is passed into Database and Collection. OperationExecutor holds reference to mongo client, but not used to implement IDisposable - which means that operation executor passed to database would be half-operational after the mongo client would be disposed. By half-operational I mean it will throw on any code path which require accessing mongo client: for example any implicit session creation will require that.
This is what I've tried to address here - I've made OperationExecutor disposable and move all disposed checks there. So now we will have consistent behaviour: once mongo client will be disposed - all databases and collections created from the client will throw. So this is a good part.
The bed part: mongo client has a number of methods to clone itself, by adjusting some settings (like WithReadConcern). Such method should create a new copy of mongo client with separate operation executor - so disposal of the original mongo client will not affect the created one. Plus we have a tests that wants to substitute implementation of the OperationExcecutor with the mock.
The only option to achieve all of that is to introduce the OperationExecutorFactory parameter - the factory method that accepts IMongoClient and returns OperationExecutor. So tests could substitute it, and clonning methods could ask for the fresh OperationExecutor.
{ | ||
[Theory] | ||
[ParameterAttributeData] | ||
public async Task StartImplicitSession_should_call_cluster([Values(true, false)]bool isAsync) |
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.
minor: _cluster_StartSession
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.
Done
|
||
namespace MongoDB.Driver | ||
{ | ||
internal record class WriteOperationOptions(); |
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.
remove class here 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.
Done
No description provided.