Skip to content
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

Cosmos: Make it possible to configure a HttpClientFactory #25399

Merged
merged 6 commits into from
Aug 7, 2021
13 changes: 13 additions & 0 deletions src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ public virtual CosmosDbContextOptionsBuilder Region(string region)
public virtual CosmosDbContextOptionsBuilder LimitToEndpoint(bool enable = true)
=> WithOption(e => e.WithLimitToEndpoint(Check.NotNull(enable, nameof(enable))));

/// <summary>
/// <para>
/// Configures the context to use a specific <see cref="HttpClient" /> factory.
/// </para>
/// <para>
/// To avoid multiple instances being created use <see langword="static" /> lambdas:
/// </para>
/// <code>.HttpClientFactory(static () => new HttpClient())</code>
/// </summary>
/// <param name="httpClientFactory">A function that returns an <see cref="HttpClient" />.</param>
public virtual CosmosDbContextOptionsBuilder HttpClientFactory(Func<HttpClient>? httpClientFactory)
=> WithOption(e => e.WithHttpClientFactory(Check.NotNull(httpClientFactory, nameof(httpClientFactory))));

/// <summary>
/// Configures the context to use the provided connection mode.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class CosmosOptionsExtension : IDbContextOptionsExtension
private int? _maxRequestsPerTcpConnection;
private bool? _enableContentResponseOnWrite;
private DbContextOptionsExtensionInfo? _info;
private Func<HttpClient>? _httpClientFactory;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down Expand Up @@ -74,6 +75,7 @@ protected CosmosOptionsExtension(CosmosOptionsExtension copyFrom)
_gatewayModeMaxConnectionLimit = copyFrom._gatewayModeMaxConnectionLimit;
_maxTcpConnectionsPerEndpoint = copyFrom._maxTcpConnectionsPerEndpoint;
_maxRequestsPerTcpConnection = copyFrom._maxRequestsPerTcpConnection;
_httpClientFactory = copyFrom._httpClientFactory;
}

/// <summary>
Expand Down Expand Up @@ -488,6 +490,29 @@ public virtual CosmosOptionsExtension ContentResponseOnWriteEnabled(bool enabled
return clone;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual Func<HttpClient>? HttpClientFactory => _httpClientFactory;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual CosmosOptionsExtension WithHttpClientFactory(Func<HttpClient>? httpClientFactory)
{
var clone = Clone();

clone._httpClientFactory = httpClientFactory;

return clone;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down Expand Up @@ -559,6 +584,7 @@ public override int GetServiceProviderHashCode()
hashCode.Add(Extension._gatewayModeMaxConnectionLimit);
hashCode.Add(Extension._maxTcpConnectionsPerEndpoint);
hashCode.Add(Extension._maxRequestsPerTcpConnection);
hashCode.Add(Extension._httpClientFactory);

_serviceProviderHash = hashCode.ToHashCode();
}
dnperfors marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -581,7 +607,8 @@ public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo
&& Extension._idleTcpConnectionTimeout == otherInfo.Extension._idleTcpConnectionTimeout
&& Extension._gatewayModeMaxConnectionLimit == otherInfo.Extension._gatewayModeMaxConnectionLimit
&& Extension._maxTcpConnectionsPerEndpoint == otherInfo.Extension._maxTcpConnectionsPerEndpoint
&& Extension._maxRequestsPerTcpConnection == otherInfo.Extension._maxRequestsPerTcpConnection;
&& Extension._maxRequestsPerTcpConnection == otherInfo.Extension._maxRequestsPerTcpConnection
&& Extension._httpClientFactory == otherInfo.Extension._httpClientFactory;

public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ public class CosmosSingletonOptions : ICosmosSingletonOptions
/// </summary>
public virtual bool? EnableContentResponseOnWrite { get; private set; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual Func<HttpClient>? HttpClientFactory { get; private set; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand All @@ -162,6 +170,7 @@ public virtual void Initialize(IDbContextOptions options)
GatewayModeMaxConnectionLimit = cosmosOptions.GatewayModeMaxConnectionLimit;
MaxTcpConnectionsPerEndpoint = cosmosOptions.MaxTcpConnectionsPerEndpoint;
MaxRequestsPerTcpConnection = cosmosOptions.MaxRequestsPerTcpConnection;
HttpClientFactory = cosmosOptions.HttpClientFactory;
}
}

Expand Down Expand Up @@ -190,6 +199,7 @@ public virtual void Validate(IDbContextOptions options)
|| MaxTcpConnectionsPerEndpoint != cosmosOptions.MaxTcpConnectionsPerEndpoint
|| MaxRequestsPerTcpConnection != cosmosOptions.MaxRequestsPerTcpConnection
|| EnableContentResponseOnWrite != cosmosOptions.EnableContentResponseOnWrite
|| HttpClientFactory != cosmosOptions.HttpClientFactory
))
{
throw new InvalidOperationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,13 @@ public interface ICosmosSingletonOptions : ISingletonOptions
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
bool? EnableContentResponseOnWrite { get; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
Func<HttpClient>? HttpClientFactory { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ public SingletonCosmosClientWrapper(ICosmosSingletonOptions options)
configuration.MaxRequestsPerTcpConnection = options.MaxRequestsPerTcpConnection.Value;
}

if (options.HttpClientFactory != null)
{
configuration.HttpClientFactory = options.HttpClientFactory;
}

_options = configuration;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public void Can_create_options_with_valid_values()
Test(
o => o.IdleTcpConnectionTimeout(TimeSpan.FromMinutes(3)),
o => Assert.Equal(TimeSpan.FromMinutes(3), o.IdleTcpConnectionTimeout));
Test(
o => o.HttpClientFactory(static () => new HttpClient()),
o => Assert.Same(httpClient, o.HttpClientFactory())
dnperfors marked this conversation as resolved.
Show resolved Hide resolved
);
}

[ConditionalFact]
Expand Down Expand Up @@ -101,4 +105,3 @@ private void Throws<T>(Action<CosmosDbContextOptionsBuilder> cosmosOptionsAction
}
}
}