-
Notifications
You must be signed in to change notification settings - Fork 351
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
Isolate scoped settings in default OData services #3071
Conversation
@@ -55,15 +55,15 @@ public static IServiceCollection AddDefaultODataServices(this IServiceCollection | |||
// Finally, register configurable settings. | |||
var readerSettings = new ODataMessageReaderSettings(odataVersion); | |||
configureReaderAction?.Invoke(readerSettings); | |||
services.AddScoped(sp => readerSettings); | |||
services.AddScoped(sp => readerSettings.Clone()); |
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.
question: Would there be an issue if we called configure reader action multiple times e.g. if we used a delegate instead of the cloned instance?
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.
Are you referring to this approach:
services.AddScope(_ => {
var readerSettings = new ODataMessageReaderSettings(...);
configureReaderAction?.Invoke(readerSettings);
return readerSettings;
});
If so, I considered it (and mentioned it in the attached issue). The reason I opted for cloning instead of that approach is because we can't predict the cost of the delegate since it's user defined, for all we know it could be reading from a file or database. On the other hand, since we control the implementation of the Clone()
method, we can make better assumptions about it cost and we can optimize if it becomes a hotspot, so I think it's safer to err on the side of calling Clone()
multiple times rather than calling the opaque user-defined delegate multiple times.
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
|
||
var writerSettings = new ODataMessageWriterSettings(odataVersion); | ||
configureWriterAction?.Invoke(writerSettings); | ||
services.AddScoped(sp => writerSettings); | ||
services.AddScoped(sp => writerSettings.Clone()); |
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.
When an ODataMessageWriterSettings
is passed as argument to an ODataMessageWriter
, the scoped ODataMessageWriterSettings
service is being updated to that 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.
@syprieur That's a very good question, apparently it does :( The settings from the ODataMessageWriterSettings
are copied to the scoped ODataMessageWriterSettings
service:
see:
- https://github.com/OData/odata.net/blob/main/src/Microsoft.OData.Core/ODataMessageWriter.cs#L110
- https://github.com/OData/odata.net/blob/main/src/Microsoft.OData.Core/ODataMessageWriterSettings.cs#L485
which calls:
internal static ODataMessageWriterSettings CreateWriterSettings(
IServiceProvider container,
ODataMessageWriterSettings other)
{
ODataMessageWriterSettings writerSettings;
if (container == null)
{
writerSettings = new ODataMessageWriterSettings();
}
else
{
// we get the scoped settings
writerSettings = container.GetRequiredService<ODataMessageWriterSettings>();
}
if (other != null)
{
// then overwrite the scoped service based on the settings passed to the writer
writerSettings.CopyFrom(other);
}
return writerSettings;
}
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.
That explains the observed bug and confirms the hypothesis: the same settings instance is indeed re-used and updated concurrently.
Your change will fix it.
Issues
*This pull request fixes #3070 *
Description
Clones the reader, writer and URI parser settings when registering them as scoped services in
AddDefaultODataServices()
to ensure that different request scopes get different copies that can be independently modified.Checklist (Uncheck if it is not completed)
Additional work necessary
If documentation update is needed, please add "Docs Needed" label to the issue and provide details about the required document change in the issue.