diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 1f86e7cc78..b52496cf8a 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -1030,7 +1030,7 @@ internal virtual void Initialize(Uri serviceEndpoint, this.ConnectionPolicy = connectionPolicy ?? ConnectionPolicy.Default; #if !NETSTANDARD16 - ServicePoint servicePoint = ServicePointManager.FindServicePoint(this.ServiceEndpoint); + ServicePointAccessor servicePoint = ServicePointAccessor.FindServicePoint(this.ServiceEndpoint); servicePoint.ConnectionLimit = this.ConnectionPolicy.MaxConnectionLimit; #endif diff --git a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs index 561074321b..9b70757e89 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs @@ -565,7 +565,7 @@ private bool CanUseMultipleWriteLocations() private void SetServicePointConnectionLimit(Uri endpoint) { #if !NETSTANDARD16 - ServicePoint servicePoint = ServicePointManager.FindServicePoint(endpoint); + ServicePointAccessor servicePoint = ServicePointAccessor.FindServicePoint(endpoint); servicePoint.ConnectionLimit = this.connectionLimit; #endif } diff --git a/Microsoft.Azure.Cosmos/src/Util/ServicePointAccessor.cs b/Microsoft.Azure.Cosmos/src/Util/ServicePointAccessor.cs new file mode 100644 index 0000000000..fc642ff054 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Util/ServicePointAccessor.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Net; + using System.Runtime.InteropServices; + using Microsoft.Azure.Cosmos.Core.Trace; + + /// + /// While ServicePoint is a NETStandard 2.0 API, not all runtimes support the operations and some Framework implementations might not support it. + /// + internal class ServicePointAccessor + { + // WebAssembly detection + private static bool IsBrowser = RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")) || RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY")); + + private readonly ServicePoint servicePoint; + + private ServicePointAccessor(ServicePoint servicePoint) + { + this.servicePoint = servicePoint ?? throw new ArgumentNullException(nameof(servicePoint)); + } + + internal static ServicePointAccessor FindServicePoint(Uri endpoint) + { + return new ServicePointAccessor(ServicePointManager.FindServicePoint(endpoint)); + } + + public int ConnectionLimit + { + get => this.servicePoint.ConnectionLimit; + set => this.TrySetConnectionLimit(value); + } + + private void TrySetConnectionLimit(int connectionLimit) + { + if (ServicePointAccessor.IsBrowser) + { + // Workaround for WebAssembly. + // WebAssembly currently throws a SynchronizationLockException and not a PlatformNotSupportedException. + return; + } + + try + { + this.servicePoint.ConnectionLimit = connectionLimit; + } + catch (PlatformNotSupportedException) + { + DefaultTrace.TraceWarning("ServicePoint.set_ConnectionLimit - Platform does not support feature."); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs new file mode 100644 index 0000000000..f5258f2b0a --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests +{ + using System; + using System.Net; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class ServicePointAccessorTests + { + private static Uri uri = new Uri("https://localhost"); + + [TestMethod] + public void ServicePointAccessor_SetConnectionLimit() + { + int limit = 10; + ServicePointAccessor accessor = ServicePointAccessor.FindServicePoint(ServicePointAccessorTests.uri); + Assert.IsNotNull(accessor); + accessor.ConnectionLimit = limit; + ServicePoint servicePoint = ServicePointManager.FindServicePoint(ServicePointAccessorTests.uri); + Assert.AreEqual(limit, servicePoint.ConnectionLimit); + } + } +}